aws-lambdalambda-authorizer

Access principalId in lambda function (python) from API Authorizer


I have an API Authorizer which works fine but I want to access the obtained principalId in my lambda function (written in python). I have seen in other answer that they suggest using template mappings but I simply can't get that to work. I have created a simple mapping with the following:

{
    "userId" : "$context.authorizer.principalId"
}

For the Content-Type: application/json And try with this two options:

But in any case when I try to access the variable on my function it gives me a keyError. I have also try with the mapping that gives you by default and access it via the "context" but I also get a keyError.

To access it I simply use:

event["userId"]

or

event["context"]

but in both cases I get keyError.

UPDATE 1: Here is the code just for reference, both the function and the authorizer work fine in the API, the only problem is when I try to get the principalId in the function.

lambda function code:

def handler(event, context):
    print(event['userId'])
    # Your code goes here!
    documento = event.get("documento")
    tipo = event.get("tipo")
    documento_bytes = base64.decodebytes(documento.encode('utf-8'))
    if tipo == "ine":
        return get_info_ine(documento_bytes)
    else:
        respuesta = {
            "estatus" : "ERROR",
            "mensaje" : "El tipo de documento <%s> enviado no existe" % tipo,
            "claveMensaje" : 2
        }
        return respuesta

Authorizer code:

import psycopg2
import base64
import re
from perfil import *


def handler(event, context):
    login_string = event["headers"]["Authorization"]
    
    login_string = re.sub('^Basic ', '', login_string)
    username, password = base64.b64decode(
        login_string).decode("UTF-8").split(':')

    connection, cursor = get_connection(hostname, dbuser, dbpass, database)

    cursor.execute("a query here")
    id = 0
    effect = "Deny"
    for record in cursor:
        id = record[0]
        effect = "Allow"

    return {
        "principalId": str(id),
        "policyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Action": "execute-api:Invoke",
                    "Effect": effect,
                    "Resource": "arn:aws:execute-api:us-west-2:12345678910:xyz/*/POST/*"
                }
            ]
        }
    }

Solution

  • In my understanding the Authorizer put the id of the user coming from the database in the PrincipalId of the generated Policy.

    The goal is to access this id in the function.

    The policy attached by the authorizer can be found on the input event object with the key attribute requestContext. The complete path is : event['requestContext']['authorizer']['principalId']

    Here is simple hello function which reads, (and outputs) the PrincipalId value from its authorizer:

    def hello(event, context):
        print('event', event)
        userId = None
        if 'requestContext' in event and 'authorizer' in event['requestContext']:
            userId = event['requestContext']['authorizer']['principalId']
        body = {
            "userId": userId,
            "event": event
        }
    
        response = {
            "statusCode": 200,
            "headers": {
                # Required for CORS support to work
                'Access-Control-Allow-Origin': '*',
                # Required for cookies, authorization headers with HTTPS
                'Access-Control-Allow-Credentials': True,
            },
            "body": json.dumps(body)
        }
    
        return response