Uso de autorizadores Lambda de API Gateway - Amazon API Gateway

Uso de autorizadores Lambda de API Gateway

Utilice un autorizador de Lambda (que anteriormente se denominaba autorizador personalizado) para controlar el acceso a su API. Cuando un cliente realiza una solicitud al método de su API, API Gateway llama a su autorizador de Lambda. El autorizador de Lambda toma la identidad del intermediario como entrada y devuelve una política de IAM como salida.

Utilice un autorizador de Lambda para implementar un esquema de autorización personalizado. El esquema puede utilizar los parámetros de la solicitud para determinar la identidad del intermediario o utilizar una estrategia de autenticación de token de portador como OAuth o SAML. Cree un autorizador de Lambda en la consola de la API de REST de API Gateway mediante la AWS CLI o un SDK de AWS.

Flujo del trabajo de autorización del autorizador de Lambda

El siguiente diagrama muestra el flujo de trabajo de autorización para un autorizador de Lambda.

Flujo de trabajo de autorización de Lambda en API Gateway
Flujo de trabajo de autorización de Lambda en API Gateway
  1. El cliente llama a un método en una API de API Gateway, pasando un token de portador o parámetros de solicitud.

  2. API Gateway comprueba si la solicitud de método está configurada con un autorizador de Lambda. Si es así, API Gateway llama a la función de Lambda.

  3. La función de Lambda autentica al intermediario. La función puede autenticarse de una de las siguientes formas:

    • Llamando a un proveedor de OAuth para obtener un token de acceso de OAuth.

    • Llamando a un proveedor de SAML para obtener una aserción de SAML.

    • Generando una política de IAM basada en los valores de los parámetros de la solicitud.

    • Recuperando credenciales de una base de datos.

  4. La función de Lambda devuelve una política de IAM y un identificador de entidad principal. Si la función de Lambda no devuelve esa información, se produce un error en la llamada.

  5. API Gateway evalúa la política de IAM.

    • Si se deniega el acceso, API Gateway devuelve un código de estado HTTP apropiado, como por ejemplo 403 ACCESS_DENIED.

    • Si se permite el acceso, API Gateway invoca el método.

      Si habilita el almacenamiento en caché, API Gateway almacena en caché la política de modo que no es necesario volver a invocar la función del autorizador de Lambda.

Puede personalizar las respuestas de la puerta de enlace 403 ACCESS_DENIED o 401 UNAUTHORIZED. Para obtener más información, consulte Respuestas de Gateway para las API de REST en API Gateway.

Elección de un tipo de autorizador de Lambda

Hay dos tipos de autorizadores Lambda:

Autorizador de Lambda basado en parámetros de solicitud (autorizador REQUEST)

Un autorizador REQUEST recibe la identidad de la persona que llama en una combinación de encabezados, parámetros de cadenas de consulta, stageVariables y variables $context. Puede usar un autorizador REQUEST para crear políticas detalladas basadas en la información de varios orígenes de identidad, como las variables de contexto $context.path y $context.httpMethod.

Si activa el almacenamiento en caché de autorizaciones para un autorizador REQUEST, API Gateway verifica que todos los orígenes de identidad especificados estén presentes en la solicitud. Si falta algún origen de identidad especificado, o bien es nulo o está vacío, API Gateway devolverá una respuesta HTTP 401 Unauthorized sin llamar a la función del autorizador de Lambda. Cuando se definen varios orígenes de identidad, se utilizan todos para obtener la clave de caché del autorizador, manteniendo el mismo orden. Puede definir una clave de caché detallada mediante el uso de varios orígenes de identidad.

Si cambia cualquiera de las partes de la clave de caché y vuelve a implementar su API, el autorizador descartará el documento de políticas almacenado en caché y generará otro nuevo.

Si desactiva el almacenamiento en caché de autorizaciones para un autorizador REQUEST, API Gateway pasa directamente la solicitud a la función de Lambda.

Autorizador de Lambda basado en token (autorizador TOKEN)

Un autorizador TOKEN recibe la identidad del intermediario en un token de portador, como, por ejemplo, un JSON Web Token (JWT) o un token de OAuth.

Si activa el almacenamiento en caché de autorizaciones para un autorizador TOKEN, el nombre del encabezado especificado en el origen del token pasará a ser la clave de caché.

Además, puede utilizar la validación del token para introducir una instrucción RegEx. API Gateway realiza la validación inicial del token de entrada con respecto a esta expresión e invoca la función del autorizador de Lambda tras una validación correcta. Esto ayuda a reducir las llamadas a la API.

La propiedad IdentityValidationExpression solo es compatible con autorizadores TOKEN. Para obtener más información, consulte Objeto x-amazon-apigateway-authorizer.

nota

Le recomendamos que utilice un autorizador REQUEST para controlar el acceso a su API. Puede controlar el acceso a su API en función de varios orígenes de identidad al utilizar un autorizador REQUEST, en comparación con un único origen de identidad al utilizar un autorizador TOKEN. Además, puede separar las claves de caché utilizando varios orígenes de identidad para un autorizador REQUEST.

Ejemplo de función de Lambda con un autorizador REQUEST

El siguiente código de ejemplo crea una función del autorizador de Lambda que permite realizar una solicitud si el encabezado HeaderAuth1, el parámetro de consulta QueryString1 y la variable de etapa de StageVar1 proporcionados por el cliente coinciden con los valores especificados de headerValue1, queryValue1 y stageValue1 respectivamente.

Node.js
// A simple request-based authorizer example to demonstrate how to use request // parameters to allow or deny a request. In this example, a request is // authorized if the client-supplied HeaderAuth1 header, QueryString1 // query parameter, and stage variable of StageVar1 all match // specified values of 'headerValue1', 'queryValue1', and 'stageValue1', // respectively. export const handler = function(event, context, callback) { console.log('Received event:', JSON.stringify(event, null, 2)); // Retrieve request parameters from the Lambda function input: var headers = event.headers; var queryStringParameters = event.queryStringParameters; var pathParameters = event.pathParameters; var stageVariables = event.stageVariables; // Parse the input for the parameter values var tmp = event.methodArn.split(':'); var apiGatewayArnTmp = tmp[5].split('/'); var awsAccountId = tmp[4]; var region = tmp[3]; var restApiId = apiGatewayArnTmp[0]; var stage = apiGatewayArnTmp[1]; var method = apiGatewayArnTmp[2]; var resource = '/'; // root resource if (apiGatewayArnTmp[3]) { resource += apiGatewayArnTmp[3]; } // Perform authorization to return the Allow policy for correct parameters and // the 'Unauthorized' error, otherwise. if (headers.HeaderAuth1 === "headerValue1" && queryStringParameters.QueryString1 === "queryValue1" && stageVariables.StageVar1 === "stageValue1") { callback(null, generateAllow('me', event.methodArn)); } else { callback("Unauthorized"); } } // Help function to generate an IAM policy var generatePolicy = function(principalId, effect, resource) { // Required output: var authResponse = {}; authResponse.principalId = principalId; if (effect && resource) { var policyDocument = {}; policyDocument.Version = '2012-10-17'; // default version policyDocument.Statement = []; var statementOne = {}; statementOne.Action = 'execute-api:Invoke'; // default action statementOne.Effect = effect; statementOne.Resource = resource; policyDocument.Statement[0] = statementOne; authResponse.policyDocument = policyDocument; } // Optional output with custom properties of the String, Number or Boolean type. authResponse.context = { "stringKey": "stringval", "numberKey": 123, "booleanKey": true }; return authResponse; } var generateAllow = function(principalId, resource) { return generatePolicy(principalId, 'Allow', resource); } var generateDeny = function(principalId, resource) { return generatePolicy(principalId, 'Deny', resource); }
Python
# A simple request-based authorizer example to demonstrate how to use request # parameters to allow or deny a request. In this example, a request is # authorized if the client-supplied headerauth1 header, QueryString1 # query parameter, and stage variable of StageVar1 all match # specified values of 'headerValue1', 'queryValue1', and 'stageValue1', # respectively. import json def lambda_handler(event, context): print(event) # Retrieve request parameters from the Lambda function input: headers = event['headers'] queryStringParameters = event['queryStringParameters'] pathParameters = event['pathParameters'] stageVariables = event['stageVariables'] # Parse the input for the parameter values tmp = event['methodArn'].split(':') apiGatewayArnTmp = tmp[5].split('/') awsAccountId = tmp[4] region = tmp[3] restApiId = apiGatewayArnTmp[0] stage = apiGatewayArnTmp[1] method = apiGatewayArnTmp[2] resource = '/' if (apiGatewayArnTmp[3]): resource += apiGatewayArnTmp[3] # Perform authorization to return the Allow policy for correct parameters # and the 'Unauthorized' error, otherwise. if (headers['HeaderAuth1'] == "headerValue1" and queryStringParameters['QueryString1'] == "queryValue1" and stageVariables['StageVar1'] == "stageValue1"): response = generateAllow('me', event['methodArn']) print('authorized') return response else: print('unauthorized') raise Exception('Unauthorized') # Return a 401 Unauthorized response # Help function to generate IAM policy def generatePolicy(principalId, effect, resource): authResponse = {} authResponse['principalId'] = principalId if (effect and resource): policyDocument = {} policyDocument['Version'] = '2012-10-17' policyDocument['Statement'] = [] statementOne = {} statementOne['Action'] = 'execute-api:Invoke' statementOne['Effect'] = effect statementOne['Resource'] = resource policyDocument['Statement'] = [statementOne] authResponse['policyDocument'] = policyDocument authResponse['context'] = { "stringKey": "stringval", "numberKey": 123, "booleanKey": True } return authResponse def generateAllow(principalId, resource): return generatePolicy(principalId, 'Allow', resource) def generateDeny(principalId, resource): return generatePolicy(principalId, 'Deny', resource)

En este ejemplo, la función del autorizador de Lambda comprueba los parámetros de entrada y actúa como se indica a continuación:

  • Si todos los valores de los parámetros necesarios coinciden con los valores previstos, la función del autorizador devuelve una respuesta HTTP 200 OK y una política de IAM que tiene un aspecto similar al siguiente, y la solicitud del método se lleva a cabo correctamente:

    { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Allow", "Resource": "arn:aws:execute-api:us-east-1:123456789012:ivdtdhp7b5/ESTestInvoke-stage/GET/" } ] }
  • De lo contrario, la función del autorizador devuelve una respuesta HTTP 401 Unauthorized y la solicitud al método produce un error.

Además de devolver una política de IAM, la función del autorizador de Lambda también debe devolver el identificador principal del intermediario. Opcionalmente, puede devolver un objeto context, que contiene información adicional que puede pasarse al backend de integración. Para obtener más información, consulte Salida de un autorizador de Lambda de API Gateway.

En el código de producción, es posible que necesite autenticar al usuario antes de conceder la autorización. En tal caso, puede agregar la lógica de autenticación a la función de Lambda llamando a un proveedor de autenticación de la forma que se indica en la documentación de ese proveedor.

Ejemplo de función de Lambda con un autorizador TOKEN

El siguiente código de ejemplo crea una función del autorizador de Lambda TOKEN que permite al intermediario invocar un método si el valor del token proporcionado por el cliente es allow. El intermediario no puede invocar la solicitud si el valor del token es deny. Si el valor del token es unauthorized o una cadena vacía, la función del autorizador devolverá una respuesta 401 UNAUTHORIZED.

Node.js
// A simple token-based authorizer example to demonstrate how to use an authorization token // to allow or deny a request. In this example, the caller named 'user' is allowed to invoke // a request if the client-supplied token value is 'allow'. The caller is not allowed to invoke // the request if the token value is 'deny'. If the token value is 'unauthorized' or an empty // string, the authorizer function returns an HTTP 401 status code. For any other token value, // the authorizer returns an HTTP 500 status code. // Note that token values are case-sensitive. export const handler = function(event, context, callback) { var token = event.authorizationToken; switch (token) { case 'allow': callback(null, generatePolicy('user', 'Allow', event.methodArn)); break; case 'deny': callback(null, generatePolicy('user', 'Deny', event.methodArn)); break; case 'unauthorized': callback("Unauthorized"); // Return a 401 Unauthorized response break; default: callback("Error: Invalid token"); // Return a 500 Invalid token response } }; // Help function to generate an IAM policy var generatePolicy = function(principalId, effect, resource) { var authResponse = {}; authResponse.principalId = principalId; if (effect && resource) { var policyDocument = {}; policyDocument.Version = '2012-10-17'; policyDocument.Statement = []; var statementOne = {}; statementOne.Action = 'execute-api:Invoke'; statementOne.Effect = effect; statementOne.Resource = resource; policyDocument.Statement[0] = statementOne; authResponse.policyDocument = policyDocument; } // Optional output with custom properties of the String, Number or Boolean type. authResponse.context = { "stringKey": "stringval", "numberKey": 123, "booleanKey": true }; return authResponse; }
Python
# A simple token-based authorizer example to demonstrate how to use an authorization token # to allow or deny a request. In this example, the caller named 'user' is allowed to invoke # a request if the client-supplied token value is 'allow'. The caller is not allowed to invoke # the request if the token value is 'deny'. If the token value is 'unauthorized' or an empty # string, the authorizer function returns an HTTP 401 status code. For any other token value, # the authorizer returns an HTTP 500 status code. # Note that token values are case-sensitive. import json def lambda_handler(event, context): token = event['authorizationToken'] if token == 'allow': print('authorized') response = generatePolicy('user', 'Allow', event['methodArn']) elif token == 'deny': print('unauthorized') response = generatePolicy('user', 'Deny', event['methodArn']) elif token == 'unauthorized': print('unauthorized') raise Exception('Unauthorized') # Return a 401 Unauthorized response return 'unauthorized' try: return json.loads(response) except BaseException: print('unauthorized') return 'unauthorized' # Return a 500 error def generatePolicy(principalId, effect, resource): authResponse = {} authResponse['principalId'] = principalId if (effect and resource): policyDocument = {} policyDocument['Version'] = '2012-10-17' policyDocument['Statement'] = [] statementOne = {} statementOne['Action'] = 'execute-api:Invoke' statementOne['Effect'] = effect statementOne['Resource'] = resource policyDocument['Statement'] = [statementOne] authResponse['policyDocument'] = policyDocument authResponse['context'] = { "stringKey": "stringval", "numberKey": 123, "booleanKey": True } authResponse_JSON = json.dumps(authResponse) return authResponse_JSON

En este ejemplo, cuando la API recibe una solicitud de método, API Gateway pasa el token de origen a esta función de autorizador de Lambda en el atributo event.authorizationToken. La función del autorizador de Lambda lee el token y actúa como se indica a continuación:

  • Si el valor del token es allow, la función del autorizador devuelve una respuesta HTTP 200 OK y una política de IAM que tiene un aspecto similar al siguiente, y la solicitud del método se lleva a cabo correctamente:

    { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Allow", "Resource": "arn:aws:execute-api:us-east-1:123456789012:ivdtdhp7b5/ESTestInvoke-stage/GET/" } ] }
  • Si el valor del token es deny, la función del autorizador devolverá una respuesta HTTP 200 OK y una política Deny de IAM similar a la siguiente y se producirá un error en la solicitud del método:

    { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Deny", "Resource": "arn:aws:execute-api:us-east-1:123456789012:ivdtdhp7b5/ESTestInvoke-stage/GET/" } ] }
    nota

    Fuera del entorno de prueba, API Gateway devuelve una respuesta HTTP 403 Forbidden y la solicitud del método produce un error.

  • Si el valor del token es unauthorized o una cadena vacía, la función del autorizador devolverá una respuesta HTTP 401 Unauthorized y la llamada al método producirá un error.

  • Si el token es cualquier otra cosa, el cliente recibirá una respuesta 500 Invalid token y la llamada al método producirá un error.

Además de devolver una política de IAM, la función del autorizador de Lambda también debe devolver el identificador principal del intermediario. Opcionalmente, puede devolver un objeto context, que contiene información adicional que puede pasarse al backend de integración. Para obtener más información, consulte Salida de un autorizador de Lambda de API Gateway.

En el código de producción, es posible que necesite autenticar al usuario antes de conceder la autorización. En tal caso, puede agregar la lógica de autenticación a la función de Lambda llamando a un proveedor de autenticación de la forma que se indica en la documentación de ese proveedor.

Ejemplos adicionales de funciones del autorizador de Lambda

En la siguiente lista, se muestran ejemplos adicionales de funciones del autorizador de Lambda. Puede crear una función de Lambda en la misma cuenta desde la que creó la API o en una cuenta diferente.

Para las funciones de Lambda del ejemplo anterior, puede utilizar el AWSLambdaBasicExecutionRole integrado, ya que estas funciones no llaman a otros servicios de AWS. Si su función de Lambda llama a otros servicios de AWS, tendrá que asignar un rol de ejecución de IAM para la función de Lambda. Para crear el rol, siga las instrucciones de Rol de ejecución de AWS Lambda.

Ejemplos adicionales de funciones del autorizador de Lambda