

# Usar os autorizadores do API Gateway Lambda
<a name="apigateway-use-lambda-authorizer"></a>

Use um *autorizador do Lambda* (anteriormente conhecido como *autorizador personalizado*) para controlar o acesso à API. Quando um cliente solicita o método da API, o API Gateway chama o autorizador do Lambda. O autorizador do Lambda usa a identidade do chamador como entrada e retorna uma política do IAM como saída.

Use um autorizador do Lambda para implementar um esquema de autorização personalizado. O esquema pode usar parâmetros de solicitação para determinar a identidade do chamador ou usar uma estratégia de autenticação de token de portador, como OAuth ou SAML. Crie um autorizador do Lambda no console da API REST do API Gateway, usando a AWS CLI ou um SDK da AWS.

## Fluxo de trabalho de autorização do autorizador do Lambda
<a name="api-gateway-lambda-authorizer-flow"></a>

O diagrama a seguir mostra o fluxo de trabalho de autorização referente a um autorizador do Lambda.

![Fluxo de trabalho de autorização do Lambda do API Gateway](http://docs.aws.amazon.com/pt_br/apigateway/latest/developerguide/images/custom-auth-workflow.png)


**Fluxo de trabalho de autorização do Lambda do API Gateway**

1. O cliente chama um método em uma API do API Gateway, passando um token de portador ou parâmetros de solicitação.

1. O API Gateway confere se a solicitação do método está configurada com um autorizador do Lambda. Se estiver, o API Gateway chama a função do Lambda.

1. A função do Lambda autentica o chamador. A função pode fazer a autenticação das seguintes maneiras:
   + Chamando um provedor OAuth para receber um token de acesso OAuth.
   + Chamando um provedor SAML para receber uma declaração SAML.
   + Gerando uma política do IAM com base nos valores do parâmetro de solicitação.
   + Recuperando as credenciais de um banco de dados.

1. A função do Lambda retorna uma política do IAM e um identificador de entidade principal. Se a função do Lambda não retornar essas informações, a chamada falhará. 

1. O API Gateway avalia a política do IAM.
   + Se o acesso for negado, o API Gateway retornará um código de status HTTP, por exemplo, `403 ACCESS_DENIED`.
   + Se o acesso for permitido, o API Gateway invocará o método. 

     Se você habilitar o armazenamento em cache da autorização, o API Gateway armazenará a política em cache para que a função do autorizador do Lamba não seja invocada novamente. Sua política deve ser aplicável a todos os recursos e métodos em sua API.

É possível personalizar as respostas `403 ACCESS_DENIED` ou `401 UNAUTHORIZED` do gateway. Para saber mais, consulte [Respostas do gateway para APIs REST no API Gateway](api-gateway-gatewayResponse-definition.md).

## Como escolher um tipo de autorizador do Lambda
<a name="api-gateway-lambda-authorizer-choose"></a>

Existem dois tipos de autorizadores do Lambda:

**Solicitar um autorizador do Lambda baseado em parâmetros (autorizador `REQUEST`)**  
Um autorizador `REQUEST` recebe a identidade do chamador em uma combinação de cabeçalhos, parâmetros de strings de consulta, [`stageVariables`](api-gateway-mapping-template-reference.md#stagevariables-template-reference) e variáveis [`$context`](api-gateway-mapping-template-reference.md#context-variable-reference). É possível usar um autorizador `REQUEST` para criar políticas refinadas com base nas informações de várias fontes de identidade, como as variáveis de contexto `$context.path` e `$context.httpMethod`.  
Se você ativar o armazenamento em cache de autorização para um autorizador `REQUEST`, o API Gateway verificará se todas as fontes de identidade especificadas estão presentes na solicitação. Se uma fonte de identidade especificada estiver ausente, for nula ou estiver vazia, o API Gateway retornará uma resposta HTTP `401 Unauthorized` sem chamar a função do autorizador do Lambda. Quando há várias fontes de identidade definidas, todas são usadas para derivar a chave de cache do autorizador, preservando a ordem. É possível definir uma chave de cache refinada usando várias fontes de identidade.  
Se você alterar qualquer parte da chave do cache e reimplantar a API, o autorizador descartará o documento da política em cache e gerará outro.  
Se você desativar o armazenamento em cache de autorização para um autorizador `REQUEST`, o API Gateway passará a solicitação diretamente à função do Lambda. 

**Autorizador do Lambda com base em token (autorizador `TOKEN`)**  
Um autorizador `TOKEN` recebe a identidade do chamador em um token de portador, como um JSON Web Token (JWT) ou um token OAuth.  
Se você ativar o armazenamento em cache de autorização para um autorizador `TOKEN`, o nome do cabeçalho especificado na origem do token será a chave do cache.   
Além disso, é possível usar a validação de token para inserir uma instrução RegEx. O API Gateway executa a validação inicial do token de entrada em relação a essa expressão e invoca a função do autorizador do Lambda mediante a validação com êxito. Isso ajuda a reduzir as chamadas para a API.   
A propriedade `IdentityValidationExpression` é compatível somente com autorizadores `TOKEN`. Para obter mais informações, consulte [Objeto x-amazon-apigateway-authorizer](api-gateway-swagger-extensions-authorizer.md).

**nota**  
Recomendamos que você use um autorizador `REQUEST` para controlar o acesso à API. É possível controlar o acesso à API com base em várias fontes de identidade ao usar um autorizador `REQUEST`, em comparação com uma única fonte de identidade ao usar um autorizador `TOKEN`. Além disso, você pode separar as chaves de cache usando várias fontes de identidade para um autorizador `REQUEST`.

## Exemplo de função do Lambda do autorizador `REQUEST`
<a name="api-gateway-lambda-authorizer-request-lambda-function-create"></a>

O código de exemplo a seguir criará uma função do autorizador do Lambda que permite uma solicitação se o cabeçalho `HeaderAuth1`, o parâmetro de consulta `QueryString1` e a variável de estágio de `StageVar1` fornecidos pelo cliente corresponderem aos valores especificados de `headerValue1`, `queryValue1` e `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(null, generateDeny('me', event.methodArn));
    }
}
     
// 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.

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')
        response = generateDeny('me', event['methodArn'])
        return 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)
```

------

Neste exemplo, a função do autorizador do Lambda verifica os parâmetros de entrada e age da seguinte forma:
+ Se todos os valores de parâmetro necessários corresponderem aos valores esperados, a função do autorizador retornará uma resposta HTTP `200 OK` e uma política do IAM que é semelhante ao seguinte, e a solicitação de método será bem-sucedida:

------
#### [ JSON ]

****  

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

------
+ Caso contrário, a função do autorizador retornará uma resposta HTTP `401 Unauthorized` e ocorrerá uma falha na solicitação do método.

Além de retornar uma política do IAM, a função de autorizador do Lambda também deve retornar o identificador principal do autor da chamada. Opcionalmente, ela pode retornar um objeto `context` com informações adicionais que podem ser passadas ao back-end de integração. Para obter mais informações, consulte [Saída de um autorizador do Lambda para o API Gateway](api-gateway-lambda-authorizer-output.md).

No código de produção, talvez seja necessário autenticar o usuário antes de conceder a autorização. É possível adicionar a lógica de autenticação à função do Lambda chamando um provedor de autenticação conforme indicado na documentação desse provedor.

## Exemplo de função do Lambda do autorizador `TOKEN`
<a name="api-gateway-lambda-authorizer-token-lambda-function-create"></a>

O código de exemplo a seguir cria uma função do Lambda do autorizador `TOKEN` que permite que um chamador invoque um método caso o valor do token fornecido pelo cliente seja `allow`. O chamador não tem permissão para invocar a solicitação caso o valor do token seja `deny`. Se o valor do token for `unauthorized` ou uma string vazia, a função do autorizador retornará uma resposta `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
```

------

Neste exemplo, quando a API recebe uma solicitação de método, o API Gateway repassa o token de origem para essa função do autorizador do Lambda no atributo `event.authorizationToken`. A função do autorizador do Lambda lê o token e age da seguinte forma:
+ Se o valor do token for `allow`, a função do autorizador retornará uma resposta HTTP `200 OK` e uma política do IAM que é semelhante ao seguinte, e a solicitação de método será bem-sucedida:

------
#### [ JSON ]

****  

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

------
+ Se o valor do token for `deny`, a função do autorizador retornará uma resposta HTTP `200 OK` e uma política do IAM `Deny` que é semelhante ao seguinte, e ocorrerá uma falha na solicitação de método:

------
#### [ JSON ]

****  

  ```
  {
    "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**  
Fora do ambiente de teste, o API Gateway retorna uma resposta HTTP `403 Forbidden` e ocorre uma falha na solicitação do método.
+ Se o valor do token for `unauthorized`, a função do autorizador retornará uma resposta HTTP `401 Unauthorized`, e ocorrerá uma falha na chamada de método.
+ Se o valor do token for diferente, o cliente receberá uma resposta `500 Invalid token`, e ocorrerá uma falha na chamada de método.

Além de retornar uma política do IAM, a função de autorizador do Lambda também deve retornar o identificador principal do autor da chamada. Opcionalmente, ela pode retornar um objeto `context` com informações adicionais que podem ser passadas ao back-end de integração. Para obter mais informações, consulte [Saída de um autorizador do Lambda para o API Gateway](api-gateway-lambda-authorizer-output.md).

No código de produção, talvez seja necessário autenticar o usuário antes de conceder a autorização. É possível adicionar a lógica de autenticação à função do Lambda chamando um provedor de autenticação conforme indicado na documentação desse provedor.

## Exemplos adicionais de funções do autorizador do Lambda
<a name="api-gateway-lambda-authorizer-lambda-function-create"></a>

A lista a seguir mostra exemplos adicionais de funções do autorizador do Lambda. É possível criar uma função do Lambda na mesma conta em que você criou a API ou em uma conta diferente.

No exemplo anterior de funções do Lambda, é possível usar a função integrada [AWSLambdaBasicExecutionRole](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html), já que essas funções não chamam outros serviços da AWS. Se a função do Lambda chamar outros serviços da AWS, será necessário atribuir um perfil de execução do IAM à função do Lambda. Para criar a função, siga as instruções na [Função de execução AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html).

**Exemplos adicionais de funções do autorizador do Lambda**
+  Para ver um exemplo de aplicação, consulte [Open Banking Brasil: amostras de autorizações](https://github.com/aws-samples/openbanking-brazilian-auth-samples) no GitHub. 
+  Para obter mais exemplos de funções do Lambda, consulte [ aws-apigateway-lambda-authorizer-blueprints](https://github.com/awslabs/aws-apigateway-lambda-authorizer-blueprints) no GitHub. 
+ É possível criar um autorizador do Lambda que autentica usuários usando grupos de usuários do Amazon Cognito e autoriza chamadores com base em um armazenamento de políticas usando o Verified Permissions. Para obter mais informações, consulte [Controlar o acesso com base nos atributos de uma identidade com o Verified Permissions](apigateway-lambda-authorizer-verified-permissions.md).
+ O console do Lambda fornece um esquema Python, que você pode usar ao selecionar **Use a blueprint (Usar um esquema)** e selecionar o esquema **api-gateway-authorizer-python**.