Untitled

 avatar
unknown
plain_text
a year ago
5.4 kB
1
Indexable
# lambda_edge_validate_token.py final version

from urllib.parse import urlencode, quote
import http.cookies as cookies
from jose import jwt
import http.client 
import base64
import boto3
import json

s3_client = boto3.client("s3")
response = s3_client.get_object(Bucket = "s3bucketchecksslvupham", Key = "data_serve_lambda_edge.json")

data = response['Body'].read().decode("utf-8")
meta_data = json.loads(data)

cognito_user_pool_id    = meta_data['cognito_user_pool_id']['value']
cognito_client_id       = meta_data['cognito_user_pool_client_id']['value']
cognito_client_secret   = meta_data['cognito_user_pool_client_secret']['value']
cognito_user_pool_url   = meta_data['cognito_user_pool_domain_url']['value']
cloudfront_domain_name  = meta_data['cloudfront_domain_name']['value']
cognito_idp_domain      = "cognito-idp.us-east-1.amazonaws.com"
    
def exchange_code_for_token(request) : 
    credentials = f"{cognito_client_id}:{cognito_client_secret}"
    credentials_bytes = credentials.encode('utf-8')
    credentials_base64 = base64.b64encode(credentials_bytes).decode('utf-8')

    headers = {
        'content-type': 'application/x-www-form-urlencoded',
        'authorization': 'Basic ' + credentials_base64
    }


    code = request['querystring'].split("=")[1]
    data = {
        'grant_type': 'authorization_code',
        'redirect_uri': f'https://{cloudfront_domain_name}/parseauth',
        'code': code
    }

    conn = http.client.HTTPSConnection(cognito_user_pool_url)
    conn.request("POST", "/oauth2/token", urlencode(data), headers)

    response = conn.getresponse()
    response_data = response.read().decode('utf-8')

    response_data = eval(response_data)
    
    print("RESPONSE_DATA THAT GET ID_TOKEN : ", response_data)

    my_cookie = cookies.SimpleCookie()
    my_cookie['token'] = response_data['access_token']
    my_cookie['token']['max-age'] = response_data['expires_in']
    my_cookie['token']['path'] = '/'
    my_cookie['token']['secure'] = True

    set_cookie_value = my_cookie.output(header = '')
    print("MY COOKIE VALUE : ", set_cookie_value)
    
    final_response = {
        'status': '302',
        'statusDescription': 'Found',
        'headers': {
            'location': [{
                'key': 'Location',
                'value': '/index.html'
            }],
        'set-cookie' : [{
            'key': 'Set-Cookie',
            'value' : set_cookie_value
        }],
        'cache-control': [{ 
            'key': 'Cache-Control',
            'value': 'no-cache'
            }]
        }
    }

    print("SET COOKIES SUCCESS, RETURN FINAL_RESPONSE ", final_response)
    return final_response


def get_key(access_token) :
    cognito_user_pool_id = meta_data['cognito_user_pool_id']['value']

    jwks_url = f"/{cognito_user_pool_id}/.well-known/jwks.json"
    
    conn = http.client.HTTPSConnection(cognito_idp_domain)
    conn.request("GET", jwks_url)
    
    response = conn.getresponse().read().decode('utf-8')
    jwks_data = eval(response)

    header = jwt.get_unverified_header(access_token)
    header_kid = header['kid']

    for item in jwks_data['keys']:
        if (item['kid'] == header_kid) : return item


# ------------------------------- VALIDATION METHOD ------------------------------- #

def verify_jwt_token(access_token) :
    cognito_user_pool_id = meta_data['cognito_user_pool_id']['value']
    
    try : 
        key = get_key(access_token)
        response = jwt.decode(
            access_token, key,
            options = {
                "verify_iss": True,
                "iss" : f"https://{cognito_idp_domain}/{cognito_user_pool_id}",
                "verify_signature": True,
                "verify_exp": True
            }
        )
        
        if (response['client_id'] == cognito_client_id) : return True
        return False 
    
    except : 
        return False
    


def lambda_handler(event, context) :
    print("EVENT FROM CLOUDFRONT : ", event)
    
    request = event['Records'][0]['cf']['request']

    if (request['uri'].startswith('/parseauth')) :
        return exchange_code_for_token(request)

    cookie = None
    if 'cookie' in request['headers'] : cookie = request['headers']['cookie'][0]['value'].split("=")[1]
    
    print("COOKIE VALUE : ", cookie)
    

    if (verify_jwt_token(cookie)) : 
        print("SUCCESSFUL VALIDATION !!!")
        return request    
    
    else :
        print("FAIL VALIDATION, UNAUTHORIZE ACCESS !!!! REDIRECT TO SIGN-IN PAGE.")
        
        redirect_uri = quote(f"https://{cloudfront_domain_name}/parseauth", safe = "")
        response = {
            'status': '302',
            'statusDescription': 'Found',
            'headers': {
                'location': [{
                    'key': 'Location',
                    'value': f'https://stylcoggoogle.auth.us-east-1.amazoncognito.com/oauth2/authorize?client_id={cognito_client_id}&response_type=code&scope=aws.cognito.signin.user.admin+email+openid+profile&redirect_uri={redirect_uri}' 
                    
                }]
            }
        }

        print("REDIRECT RESPONSE TO COGNITO SIGN-IN : ", response)
        return response