1
votes

I am using a custom authorizer for my aws serverless app.

I have a cognito user pool. The workflow I am trying to accomplish is

  1. Client signs in to cognito user pool
  2. Client gets token id_token to make future api calls
  3. User hits a GET request on my getUserInfo api endpoint, passing along the token
  4. The lambda function uses the token to verify a) that the user is logged in, and b) that the user's token matches the user_name for which information is being requested

My understanding is that #4 can be accomplished by interrogating the context object for an authorizer.principalId attribute, based on this aws documentation.

However, when I test the endpoint, my context object in the python lambda does not contain this authorizer property.

The property dump for the context object from CloudWatch is as follows:

{'aws_request_id': 'a37a1735-0ef3-*****-7fb1226218fe', 'log_group_name': '/aws/lambda/****', 'log_stream_name': '2019/01/03/[$LATEST]cca175ae1ff64cb699******', 'function_name': '*****getUser', 'memory_limit_in_mb': '1024', 'function_version': '$LATEST', 'invoked_function_arn': 'arn:aws:lambda:us-east-1:*********getUser', 'client_context': None, 'identity': <__main__.CognitoIdentity object at 0x7f1caf1bbdd8>}

My python lambda is of the form:

def getUser(event, context):
    print(context)
    print(context.__dict__)
    print(context.authorizer)
    print(context.identity.__dict__)
    print(event.__dict__)
    ...

How can I make my lambda retrieve the required info so that I can verify the username from the incoming token?

2
Are you using Lambda Proxy Integration?Noel Llevares
@dashmug Yes. I just discovered that the authorization info regarding the cognito user pool was embedded as event['requestContext']['authorizer']deseosuho
Yes. That should answer your question.Noel Llevares

2 Answers

0
votes

The needed authorization info is available to the lambda function within the event parameter. For this case, what I needed was event['requestContext']['authorizer']['cognito:username']

0
votes

May be following code help you.

from __future__ import print_function
import boto3
import botocore.exceptions
import hmac
import hashlib
import base64
import json
import uuid
import logging
#Demo pool
USER_POOL_ID='ca-central-1_vaquarkhan'
CLIENT_ID ='vaquarkhanxxxxxxxxxxxxf7h8i9sc7ur6' # replace urs 
CLIENT_SECRET='vaquarkhanbryyyyyyyyyyyyyyyyhlk7ncv85qo5gjia1mdp9'# replace urs 


logger = logging.getLogger()
logger.setLevel(logging.INFO)

client = None

def get_secret_hash(username):
   msg = username + CLIENT_ID
   dig = hmac.new(str(CLIENT_SECRET).encode('utf-8'), 
   msg = str(msg).encode('utf-8'), digestmod=hashlib.sha256).digest()
   d2 = base64.b64encode(dig).decode()
 return d2

ERROR = 0
SUCCESS = 1
USER_EXISTS = 2


def sign_up(username,password):
   try:
     resp = client.sign_up(
         ClientId=CLIENT_ID ,
         SecretHash= get_secret_hash(username),
         Username=username,
         Password=password )
         print(resp)
         #except client.exceptions.UserNotFoundException as e:
         except client.exceptions.UsernameExistsException as e:
    return USER_EXISTS
    except Exception as e:
    print(e)
    logger.error(e)
    return ERROR
  return SUCCESS

def initiate_auth(username, password):
   try:
    # AdminInitiateAuth
      resp = client.admin_initiate_auth(
        UserPoolId=USER_POOL_ID,
        ClientId=CLIENT_ID,
        AuthFlow='ADMIN_NO_SRP_AUTH',
        AuthParameters={
            'USERNAME': username,
            'SECRET_HASH': get_secret_hash(username),
            'PASSWORD': password
          },
         ClientMetadata={
            'username': username,
            'password': password
           })
       except client.exceptions.NotAuthorizedException as e:
      return None, "The username or password incorrect"
    except client.exceptions.UserNotFoundException as e:
    return None, "Unauthorized"
    except Exception as e:
    print(e)
    logger.error(e)
    return None, "Unknown error"
return resp, None

def lambda_handler(event, context):
  global client
  if client == None:
    client = boto3.client('cognito-idp')

   print(event)
   body = event
   username = body['username']
   password = body['password']

   is_new ="false"
   user_id=str(uuid.uuid4())
  signed_up = sign_up(username,password)
  if signed_up == ERROR :
    return {'status':'fail','msg':'failed to sign up'}
  if signed_up == SUCCESS:
    is_new="true"

  resp,msg =initiate_auth(username,password)    

   if msg != None :
      logger.info('failed signIN with username={}'.format(username))
    return {'status':'fail','msg':msg}

id_token =resp['AuthenticationResult']['IdToken']
print('id token: '+id_token)
return {'status': 'success', 'id_token': id_token, 'user_id':user_id,'is_new':is_new}