Skip to content

Instantly share code, notes, and snippets.

@limbuu
Created March 4, 2021 18:11
Show Gist options
  • Select an option

  • Save limbuu/481f6cee7fce41f9b937d5f8114a121d to your computer and use it in GitHub Desktop.

Select an option

Save limbuu/481f6cee7fce41f9b937d5f8114a121d to your computer and use it in GitHub Desktop.

Revisions

  1. Manshi Limbu created this gist Mar 4, 2021.
    80 changes: 80 additions & 0 deletions AWSCognito-IDTOKEN-DECODER
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,80 @@
    # Copyright 2017-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
    #
    # Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file
    # except in compliance with the License. A copy of the License is located at
    #
    # http://aws.amazon.com/apache2.0/
    #
    # or in the "license" file accompanying this file. This file is distributed on an "AS IS"
    # BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    # License for the specific language governing permissions and limitations under the License.

    import json
    import time
    import urllib.request
    from jose import jwk, jwt
    from jose.utils import base64url_decode

    region = 'us-west-2'
    userpool_id = 'us-west-2_VleK3m9Np'
    app_client_id = '4ldj7ouk0hqa0cnijchmu6g8ra'
    keys_url = 'https://cognito-idp.{}.amazonaws.com/{}/.well-known/jwks.json'.format(region, userpool_id)
    # instead of re-downloading the public keys every time
    # we download them only on cold start
    # https://aws.amazon.com/blogs/compute/container-reuse-in-lambda/
    with urllib.request.urlopen(keys_url) as f:
    response = f.read()
    keys = json.loads(response.decode('utf-8'))['keys']

    def lambda_handler(event, context):
    token = event['token']
    # get the kid from the headers prior to verification
    headers = jwt.get_unverified_headers(token)
    print("************888888")
    kid = headers['kid']
    # search for the kid in the downloaded public keys
    key_index = -1
    for i in range(len(keys)):
    if kid == keys[i]['kid']:
    key_index = i
    break
    if key_index == -1:
    print('Public key not found in jwks.json')
    return False
    # construct the public key
    public_key = jwk.construct(keys[key_index])
    # get the last two sections of the token,
    # message and signature (encoded in base64)
    message, encoded_signature = str(token).rsplit('.', 1)
    # decode the signature
    decoded_signature = base64url_decode(encoded_signature.encode('utf-8'))
    # verify the signature
    if not public_key.verify(message.encode("utf8"), decoded_signature):
    print('Signature verification failed')
    return False
    print('Signature successfully verified')
    # since we passed the verification, we can now safely
    # use the unverified claims
    claims = jwt.get_unverified_claims(token)
    # additionally we can verify the token expiration
    if time.time() > claims['exp']:
    print('Token is expired')
    return False
    # and the Audience (use claims['client_id'] if verifying an access token)
    if claims['aud'] != app_client_id:
    print('Token was not issued for this audience')
    return False
    # now we can use the claims
    print(claims)
    roles = []
    if 'cognito:groups' in claims:
    roles.append(claims['cognito:groups'])
    print(roles)
    return claims

    # the following is useful to make this script executable in both
    # AWS Lambda and any other local environments
    if __name__ == '__main__':
    # for testing locally you can enter the JWT ID Token here
    event = {'token': 'eyJraWQiOiIrNGVVejhBU0RzOStVNDNjWTZ1TGtHR3k5Q0N1bXp4bzgyWVFVWVdVdVUwPSIsImFsZyI6IlJTMjU2In0.eyJhdF9oYXNoIjoiM0J6WWhOTUtLakpGdVRhM012a3hRUSIsInN1YiI6IjA2MmIwNGIyLWZlMTItNDlkYi1hYThlLTZiMmI0NzcwOTk2MiIsImF1ZCI6IjRsZGo3b3VrMGhxYTBjbmlqY2htdTZnOHJhIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInRva2VuX3VzZSI6ImlkIiwiYXV0aF90aW1lIjoxNjE0ODU5NTkzLCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZHAudXMtd2VzdC0yLmFtYXpvbmF3cy5jb21cL3VzLXdlc3QtMl9WbGVLM205TnAiLCJjb2duaXRvOnVzZXJuYW1lIjoiMDYyYjA0YjItZmUxMi00OWRiLWFhOGUtNmIyYjQ3NzA5OTYyIiwiZXhwIjoxNjE0ODYzMTkzLCJpYXQiOjE2MTQ4NTk1OTMsImVtYWlsIjoiZXR3ZWFrMUBnbWFpbC5jb20ifQ.mxlKKe_XIfP4u2X_GdkNUTfOYbCO40GNqNLzHZFPj-AtDIAdlj3LdilHnrR6RsDF6SoJKn-rVydKNjZPJ_hgNwd4n_WTqKMBp8faY90wMwBIdUq-enp8WF5E-taokBCInBDBlRSX7n8rCNNH_avJ6QqqitL8lwbfR33F-39ECdfDGnjK-btkycv8WGrEMTEh5ZWY6xktLcxj-7FGZmgSkeYUrGauvr0wYuvW_q-60TdQRaAxZa13_EurM7HspblnUR-wNbUgd3wkVMedMXCZt4u0qyY5AIIHRmLfKznsTCs-yKwTj883p5IKyPcA4f8hHRy92LqThluuGQZZv7Tc8Q'}
    lambda_handler(event, None)