Autenticar usuários usando um Application Load Balancer - Elastic Load Balancing

Autenticar usuários usando um Application Load Balancer

Você pode configurar um Application Load Balancer para autenticar usuários com segurança conforme eles acessem suas aplicações. Com isso, você pode redirecionar o trabalho de autenticação de usuários para seu load balancer para que seus aplicativos possam se concentrar na respectiva lógica de negócios.

Os casos de uso a seguir são comportados:

  • Autentique usuários por meio de um provedor de identidade (IdP) compatível com OpenID Connect (OIDC).

  • Autentique usuários por meio de IdPs sociais, como Amazon, Facebook ou Google, e de grupos de usuários compatíveis com o Amazon Cognito.

  • Autentique usuários por meio de identidades corporativas, usando SAML, OpenID Connect (OIDC) ou OAuth, por meio dos grupos de usuários compatíveis com o Amazon Cognito.

Preparação para usar um IdP compatível com OIDC

Faça o seguinte se você estiver usando um IdP compatível com OIDC com seu Application Load Balancer:

  • Crie um novo aplicativo OIDC em seu IdP. O DNS do IdP deve ser resolvível publicamente.

  • Você deve configurar um ID de cliente e um segredo de cliente.

  • Obtenha os seguintes endpoints publicados pelo IdP: autorização, token e informações de usuário. Você pode localizar essa informação na configuração.

  • Os certificados de endpoints do IdP devem ser emitidos por uma autoridade de certificação pública confiável.

  • As entradas de DNS dos endpoints devem ser resolvíveis publicamente, mesmo que sejam resolvidas em endereços IP privados.

  • Permita um dos seguintes URLs de redirecionamento no aplicativo de IdP que seus usuários utilizarão, no qual o DNS é o nome de domínio de seu balanceador de carga e CNAME é o alias de DNS da sua aplicação:

    • https://DNS/oauth2/idpresponse

    • https://CNAME/oauth2/idpresponse

Preparação para usar o Amazon Cognito

A integração do Amazon Cognito para Application Load Balancers está disponível nas seguintes regiões:

  • Leste dos EUA (Norte da Virgínia)

  • Leste dos EUA (Ohio)

  • Oeste dos EUA (N. da Califórnia)

  • Oeste dos EUA (Oregon)

  • Canadá (Central)

  • Europa (Estocolmo)

  • Europa (Milão)

  • Europa (Frankfurt)

  • Europa (Zurique)

  • Europa (Irlanda)

  • Europa (Londres)

  • Europa (Paris)

  • América do Sul (São Paulo)

  • Ásia-Pacífico (Tóquio)

  • Ásia-Pacífico (Seul)

  • Asia Pacific (Osaka)

  • Ásia-Pacífico (Mumbai)

  • Ásia-Pacífico (Singapura)

  • Ásia-Pacífico (Sydney)

  • Ásia-Pacífico (Jacarta)

  • Oriente Médio (Emirados Árabes Unidos)

  • Oriente Médio (Barém)

  • África (Cidade do Cabo)

  • Israel (Tel Aviv)

Faça o seguinte se você estiver usando grupos de usuários do Amazon Cognito com seu Application Load Balancer:

  • Criar um grupo de usuários. Para obter mais informações, consulte Grupos de usuários do Amazon Cognito no Guia do desenvolvedor do Amazon Cognito.

  • Crie um cliente de grupo de usuários. Você deve configurar o cliente para gerar um segredo de cliente, usar um fluxo de concessão de código e comportar os mesmos escopos OAuth usados pelo load balancer. Para obter mais informações, consulte Configurar um cliente de aplicativo de grupo de usuários no Guia do desenvolvedor do Amazon Cognito.

  • Crie um domínio de grupo de usuários. Para obter mais informações, consulte Adicionar um nome de domínio ao grupo de usuários no Guia do desenvolvedor do Amazon Cognito.

  • Verifique se o escopo solicitado retorna um token de ID. Por exemplo, o escopo padrão, openid retorna um token de ID, mas o aws.cognito.signin.user.admin escopo não.

    Observação: os Application Load Balancers não oferecem suporte a tokens de acesso personalizados emitidos pelo Amazon Cognito. Para obter mais informações, consulte Pre token generation no Guia do desenvolvedor do Amazon Cognito.

  • Para federar com um IdP social ou corporativo, habilite o IdP na seção de federação. Para obter mais informações, consulte Adicionar um login social a um grupo de usuários ou Adicionar login com um provedor de identidade SAML a um grupo de usuários no Guia do desenvolvedor do Amazon Cognito.

  • Permita um dos seguintes URLs de redirecionamento no campo de URL de retorno de chamada para o Amazon Cognito, no qual DNS é o nome de domínio de seu balanceador de carga e CNAME é o alias DNS da sua aplicação (se estiver usando uma):

    • https://DNS/oauth2/idpresponse

    • https://CNAME/oauth2/idpresponse

  • Permita o domínio do grupo de usuários no URL de retorno de chamada do aplicativo do IdP. Use o formato de seu IdP. Por exemplo:

    • https://domain-prefix.auth.região. amazoncognito.com/saml2/idpresponse

    • https://user-pool-domain/oauth2/idpresponse

O URL de retorno de chamada nas configurações do aplicativo cliente deve usar todas as letras minúsculas.

Para permitir que um usuário configure um balanceador de carga para usar o Amazon Cognito para autenticar usuários, você deve conceder permissão ao usuário para chamar a ação cognito-idp:DescribeUserPoolClient.

Preparação para usar o Amazon CloudFront

Habilite as seguintes configurações se você estiver usando uma distribuição do CloudFront na frente de seu Application Load Balancer:

  • Encaminhar cabeçalhos de solicitação (todos): garante que o CloudFront não armazene em cache as respostas para solicitações autenticadas. Isso impede que sejam exibidos no cache após a expiração da sessão de autenticação. Como alternativa, para reduzir esse risco enquanto o armazenamento em cache estiver ativado, os proprietários de uma distribuição do CloudFront podem definir o valor de time-to-live (TTL) a ser expirado antes que o cookie de autenticação expire.

  • Encaminhamento e armazenamento em cache de string de consulta (todos): garante que o balanceador de carga tenha acesso aos parâmetros da string de consulta necessários para autenticar o usuário com o IdP.

  • Encaminhamento de cookies (todos): garante que o CloudFront encaminhe todos os cookies de autenticação para o balanceador de carga.

Configurar a autenticação de usuários

Você configura a autenticação de usuários criando uma ação de autenticação para uma ou mais regras do listener. Os tipos de ação authenticate-cognito e authenticate-oidc são comportados somente por listeners HTTPS. Para obter as descrições dos campos correspondentes, consulte AuthenticateCognitoActionConfig e AuthenticateOidcActionConfig na referência de API do Elastic Load Balancing versão de 01/12/2015.

O load balancer envia um cookie de sessão para o cliente a fim de manter o status de autenticação. Esse cookie sempre contém o atributo secure, pois a autenticação do usuário requer um listener HTTPS. Esse cookie contém o atributo SameSite=None com solicitações CORS (cross-origin resource sharing, compartilhamento de recursos de origem cruzada).

Para um balanceador de carga compatível com várias aplicações que exigem autenticação independente de cliente, cada regra de receptor com uma ação de autenticação deve ter um nome de cookie exclusivo. Isso garante que os clientes sempre sejam autenticados com o IdP antes de serem roteados para o grupo de destino especificado na regra.

Os Application Load Balancers não são compatíveis com valores de cookie codificados por URL.

Por padrão, o campo SessionTimeout é definido com 7 dias. Se desejar sessões menores, pode configurar um tempo limite de sessão de 1 segundo. Para ter mais informações, consulte Tempo limite de sessão.

Defina o campo OnUnauthenticatedRequest de acordo com seu aplicativo. Por exemplo:

  • Aplicações que exigem que o usuário faça login usando uma identidade social ou corporativa: viabilizado pela opção padrão, authenticate. Se o usuário não estiver conectado, o load balancer redirecionará a solicitação para o endpoint de autorização do IdP e o IdP solicitará que o usuário faça login usando sua interface de usuário.

  • Aplicações que oferecem uma visualização personalizada para um usuário que está conectado ou uma visualização geral para um usuário que não está conectado: para viabilizar esse tipo de aplicação, use a opção allow. Se o usuário estiver conectado, o load balancer fornecerá as solicitações do usuário e o aplicativo poderá oferecer uma visualização personalizada. Se o usuário não estiver conectado, o load balancer encaminhará a solicitação sem as solicitações do usuário e o aplicativo poderá oferecer uma visualização geral.

  • Aplicações de página única com JavaScript que carrega a cada poucos segundos: se você usar a opção deny, o balanceador de carga retornará um erro HTTP 401 Não autorizado para chamadas AJAX que não tenham informações de autenticação. Porém, se o usuário tiver informações de autenticação expiradas, ele redirecionará o cliente para o endpoint de autorização do IdP.

O load balancer precisa se comunicar com o endpoint de token do IdP (TokenEndpoint) e o endpoint de informações do usuário do Idp (UserInfoEndpoint). Os Application Load Balancers só oferecem suporte a IPv4 ao se comunicar com esses endpoints. Se seu IdP usa endereços públicos, garanta que os grupos de segurança do balanceador de carga e as ACLs de rede da VPC permitam acesso aos endpoints. Ao usar um balanceador de carga interno ou o tipo de endereço IP dualstack-without-public-ipv4, um gateway NAT pode permitir que o balanceador de carga se comunique com os endpoints. Para obter mais informações, consulte Fundamentos de gateway NAT no Guia do usuário da Amazon VPC.

Use o comando create-rule a seguir para configurar a autenticação de usuários.

aws elbv2 create-rule --listener-arn listener-arn --priority 10 \ --conditions Field=path-pattern,Values="/login" --actions file://actions.json

Veja a seguir um exemplo do arquivo actions.json que especifica uma ação authenticate-oidc e uma ação forward. AuthenticationRequestExtraParams permite que você transmita parâmetros extras para um IdP durante a autenticação. Siga a documentação fornecida pelo seu provedor de identidade para determinar os campos que são compatíveis

[{ "Type": "authenticate-oidc", "AuthenticateOidcConfig": { "Issuer": "https://idp-issuer.com", "AuthorizationEndpoint": "https://authorization-endpoint.com", "TokenEndpoint": "https://token-endpoint.com", "UserInfoEndpoint": "https://user-info-endpoint.com", "ClientId": "abcdefghijklmnopqrstuvwxyz123456789", "ClientSecret": "123456789012345678901234567890", "SessionCookieName": "my-cookie", "SessionTimeout": 3600, "Scope": "email", "AuthenticationRequestExtraParams": { "display": "page", "prompt": "login" }, "OnUnauthenticatedRequest": "deny" }, "Order": 1 }, { "Type": "forward", "TargetGroupArn": "arn:aws:elasticloadbalancing:region-code:account-id:targetgroup/target-group-name/target-group-id", "Order": 2 }]

Veja a seguir um exemplo de configuração do arquivo actions.json, que especifica uma ação authenticate-cognito e uma ação forward.

[{ "Type": "authenticate-cognito", "AuthenticateCognitoConfig": { "UserPoolArn": "arn:aws:cognito-idp:region-code:account-id:userpool/user-pool-id", "UserPoolClientId": "abcdefghijklmnopqrstuvwxyz123456789", "UserPoolDomain": "userPoolDomain1", "SessionCookieName": "my-cookie", "SessionTimeout": 3600, "Scope": "email", "AuthenticationRequestExtraParams": { "display": "page", "prompt": "login" }, "OnUnauthenticatedRequest": "deny" }, "Order": 1 }, { "Type": "forward", "TargetGroupArn": "arn:aws:elasticloadbalancing:region-code:account-id:targetgroup/target-group-name/target-group-id", "Order": 2 }]

Para ter mais informações, consulte Regras do listener.

Fluxo de autenticação

O diagrama de rede a seguir é uma representação visual de como um Application Load Balancer usa o OIDC para autenticar usuários.

Como o Application Load Balancer autentica usuários com o OIDC

Os itens numerados abaixo destacam e explicam os elementos apresentados no diagrama de rede anterior.

  1. O usuário envia uma solicitação HTTPS para um site hospedado atrás de um Application Load Balancer. Quando as condições para uma regra com uma ação de autenticação são atendidas, o load balancer verifica a existência de um cookie de sessão de autenticação nos cabeçalhos de solicitação.

  2. Se o cookie não estiver presente, o load balancer redirecionará o usuário para o endpoint de autorização do IdP para que o IdP possa autenticar o usuário.

  3. Depois que o usuário é autenticado, o IdP envia o usuário de volta para o balanceador de carga com um código de concessão de autorização.

  4. O balanceador de carga apresenta o código de concessão de autorização ao endpoint do token do IdP.

  5. Ao receber um código de concessão de autorização válido, o IdP fornece o token de ID e o token de acesso ao Application Load Balancer.

  6. Em seguida, o Application Load Balancer envia o token de acesso ao endpoint de informações do usuário.

  7. O endpoint de informações do usuário troca o token de acesso pelas reivindicações do usuário.

  8. O Application Load Balancer redireciona o usuário com o cookie de sessão de autenticação AWSELB para o URI original. Como a maioria dos navegadores restringe o tamanho dos cookies a 4 K, o balanceador de carga fragmenta cookies com tamanho superior a 4 K em vários cookies. Se o tamanho total das solicitações do usuário e do token de acesso recebidos do IdP for superior a 11K bytes, o load balancer retornará um erro HTTP 500 para o cliente e incrementará a métrica ELBAuthUserClaimsSizeExceeded.

  9. O Application Load Balancer valida o cookie e encaminha as informações do usuário para destinos no conjunto de cabeçalhos HTTP X-AMZN-OIDC-*. Para ter mais informações, consulte Verificação de assinatura e codificação de reivindicações de usuário.

  10. O destino envia uma resposta de volta ao Application Load Balancer.

  11. O Application Load Balancer envia a resposta final ao usuário.

Cada nova solicitação passa pelas etapas de 1 a 11, enquanto as solicitações subsequentes passam pelas etapas de 9 a 11. Ou seja, todas as solicitações subsequentes começam na etapa 9, desde que o cookie não tenha expirado.

O cookie AWSALBAuthNonce é adicionado ao cabeçalho da solicitação depois que o usuário fizer autenticação no IdP. Isso não muda a forma como o Application Load Balancer processa as solicitações de redirecionamento do IdP.

Se o IdP fornecer um token de atualização válido no token de ID, o load balancer salvará o token de atualização e o usará para atualizar as solicitações do usuário toda vez que o token de acesso expirar, até o momento em que a sessão expirar ou a atualização do IdP falhar. Se o usuário encerrar a sessão, a atualização falhará e o load balancer o redirecionará para o endpoint de autorização do IdP. Isso permite que o load balancer suspenda as sessões depois que o usuário encerra a sessão. Para ter mais informações, consulte Tempo limite de sessão.

nota

A expiração do cookie é diferente da expiração da sessão de autenticação. A expiração do cookie é um atributo do cookie e que está definido para 7 dias. A duração real da sessão de autenticação é determinada pelo tempo limite da sessão configurado no Application Load Balancer para o recurso de autenticação. O tempo limite dessa sessão está incluído no valor do cookie Auth, que também é criptografado.

Verificação de assinatura e codificação de reivindicações de usuário

Depois que o load balancer autentica com êxito um usuário, envia as solicitações do usuário recebidas do IdP para o destino. O load balancer assina a solicitação do usuário para que os aplicativos possam verificar a assinatura e verificar se as solicitações foram enviadas pelo load balancer.

O load balancer adiciona os seguintes cabeçalhos HTTP:

x-amzn-oidc-accesstoken

O token de acesso do endpoint de token, em texto simples.

x-amzn-oidc-identity

O campo de assunto (sub) do endpoint de informações do usuário, em texto simples.

Obs.: a subreivindicação é a melhor maneira de identificar um usuário específico.

x-amzn-oidc-data

As solicitações do usuário, no formato de JSON Web Token (JWT).

Os tokens de acesso e as reivindicações de usuário são diferentes dos tokens de ID. Os tokens de acesso e as reivindicações de usuário só permitem o acesso aos recursos do servidor, enquanto os tokens de ID contêm informações adicionais para autenticar um usuário. O Application Load Balancer cria um token de acesso ao autenticar um usuário e apenas transmite os tokens de acesso e as declarações para o backend, porém não transmite as informações do token de ID.

Esses tokens seguem o formato JWT, mas não são tokens de ID. O formato JWT inclui um cabeçalho, carga e assinatura que são codificados em URL base64 e incluem caracteres de preenchimento no final. Um Application Load Balancer usa ES256 (ECDSA usando P-256 e SHA256) para gerar a assinatura JWT.

O cabeçalho JWT contém um objeto JSON com os seguintes campos:

{ "alg": "algorithm", "kid": "12345678-1234-1234-1234-123456789012", "signer": "arn:aws:elasticloadbalancing:region-code:account-id:loadbalancer/app/load-balancer-name/load-balancer-id", "iss": "url", "client": "client-id", "exp": "expiration" }

A carga JWT é um objeto JSON que contém o usuário as solicitações do usuário recebidas do endpoint de informações do usuário do IdP.

{ "sub": "1234567890", "name": "name", "email": "alias@example.com", ... }

Se quiser que o balanceador de carga criptografe suas declarações de usuário, você deve configurar seu grupo de destino para usar HTTPS. Além disso, como prática de segurança, recomendamos que você restrinja seus destinos para receber apenas tráfego do seu Application Load Balancer. Você pode fazer isso configurando o grupo de segurança de seus destinos para fazer referência ao ID do grupo de segurança do balanceador de carga.

Para garantir a segurança, você deve verificar a assinatura antes de fazer qualquer autorização com base nas declarações e validar se o campo signer no cabeçalho JWT contém o ARN esperado do Application Load Balancer.

Para obter a chave pública, obtenha o ID de chave de cabeçalho JWT e use-o para procurar a chave pública do endpoint. O endpoint para cada região da AWS é o seguinte:

https://public-keys.auth.elb.region.amazonaws.com/key-id

Para a AWS GovCloud (US), os endpoints são os seguintes:

https://s3-us-gov-west-1.amazonaws.com/aws-elb-public-keys-prod-us-gov-west-1/key-id https://s3-us-gov-east-1.amazonaws.com/aws-elb-public-keys-prod-us-gov-east-1/key-id

O exemplo a seguir mostra como obter o ID de chave, a chave pública e a carga útil em Python 3.x:

import jwt import requests import base64 import json # Step 1: Validate the signer expected_alb_arn = 'arn:aws:elasticloadbalancing:region-code:account-id:loadbalancer/app/load-balancer-name/load-balancer-id' encoded_jwt = headers.dict['x-amzn-oidc-data'] jwt_headers = encoded_jwt.split('.')[0] decoded_jwt_headers = base64.b64decode(jwt_headers) decoded_jwt_headers = decoded_jwt_headers.decode("utf-8") decoded_json = json.loads(decoded_jwt_headers) received_alb_arn = decoded_json['signer'] assert expected_alb_arn == received_alb_arn, "Invalid Signer" # Step 2: Get the key id from JWT headers (the kid field) kid = decoded_json['kid'] # Step 3: Get the public key from regional endpoint url = 'https://public-keys.auth.elb.' + region + '.amazonaws.com/' + kid req = requests.get(url) pub_key = req.text # Step 4: Get the payload payload = jwt.decode(encoded_jwt, pub_key, algorithms=['ES256'])

O exemplo a seguir mostra como obter o ID de chave, a chave pública e a carga útil em Python 2.7:

import jwt import requests import base64 import json # Step 1: Validate the signer expected_alb_arn = 'arn:aws:elasticloadbalancing:region-code:account-id:loadbalancer/app/load-balancer-name/load-balancer-id' encoded_jwt = headers.dict['x-amzn-oidc-data'] jwt_headers = encoded_jwt.split('.')[0] decoded_jwt_headers = base64.b64decode(jwt_headers) decoded_json = json.loads(decoded_jwt_headers) received_alb_arn = decoded_json['signer'] assert expected_alb_arn == received_alb_arn, "Invalid Signer" # Step 2: Get the key id from JWT headers (the kid field) kid = decoded_json['kid'] # Step 3: Get the public key from regional endpoint url = 'https://public-keys.auth.elb.' + region + '.amazonaws.com/' + kid req = requests.get(url) pub_key = req.text # Step 4: Get the payload payload = jwt.decode(encoded_jwt, pub_key, algorithms=['ES256'])
Considerações
  • Esses exemplos não abordam como validar a assinatura do emissor com a assinatura no token.

  • As bibliotecas padrão não são compatíveis com o preenchimento incluído no token de autenticação do Application Load Balancer no formato JWT.

Timeout (Tempo limite)

Tempo limite de sessão

O token de atualização e o tempo limite de sessão funcionam juntos da seguinte forma:

  • Se o tempo limite da sessão for menor do que a expiração do token de acesso, o load balancer respeitará o tempo limite da sessão. Se o usuário tiver uma sessão ativa com o IdP, talvez o usuário não seja solicitado a fazer login novamente. Caso contrário, o utilizador será redirecionado para fazer login.

    • Se o tempo limite de sessão do IdP for superior ao tempo limite de sessão do Application Load Balancer, o usuário não precisará fornecer credenciais para fazer login novamente. Em vez disso, o IdP o redirecionará para o Application Load Balancer com um novo código de concessão de autorização. Os códigos de autorização são de uso único, mesmo que não haja um novo login.

    • Se o tempo limite de sessão do IdP for igual ou inferior ao tempo limite de sessão do Application Load Balancer, o usuário será solicitado a fornecer credenciais para fazer login novamente. Após o login do usuário, o IdP o redirecionará para o Application Load Balancer com um novo código de concessão de autorização, e o restante do fluxo de autenticação continuará até que a solicitação chegue ao back-end.

  • Se o tempo limite da sessão for superior ao tempo de expiração do token de acesso e o IdP não for compatível com tokens de atualização, o balanceador de carga manterá a sessão de autenticação até sua expiração. Em seguida, ele forçará o usuário a fazer login novamente.

  • Se o tempo limite de sessão for maior do que o tempo de expiração do token de acesso e o IdP comportar tokens de atualização, o load balancer atualizará a sessão de usuário toda vez que o token de acesso expirar. O load balancer fará com que o usuário faça login novamente apenas depois que a sessão de autenticação expirar ou o fluxo de atualização falhar.

Tempo limite de login do cliente

O cliente deve iniciar e concluir o processo de autenticação em até 15 minutos. Se um cliente não conseguir concluir a autenticação durante os 15 minutos, ele receberá um erro HTTP 401 do balanceador de carga. Não é possível alterar nem remover esse tempo limite.

Por exemplo, se um usuário carregar a página de login por meio do Application Load Balancer, ele deverá concluir o processo de login em até 15 minutos. Se o usuário esperar e tentar fazer login após a expiração do tempo limite de 15 minutos, o balanceador de carga retornará um erro HTTP 401. O usuário precisará atualizar a página e tentar fazer login novamente.

Sair da autenticação

Quando um aplicativo precisa encerrar a sessão de um usuário autenticado, deve definir o tempo de expiração do cookie de sessão de autenticação como –1 e redirecionar o cliente para o endpoint de logout do IdP (se o IdP comportar um). Para evitar que os usuários reutilizem um cookie excluído, é recomendável configurar um tempo de expiração o mais razoável possível para o token de acesso. Se um cliente fornecer um balanceador de carga com um cookie de sessão que contenha um token de acesso expirado com um token de atualização não nulo, o balanceador de carga entrará em contato com o IdP para determinar se o usuário ainda está conectado.

A página inicial de logout do cliente é uma página não autenticada. Isso significa que ela não pode estar protegida por uma regra do Application Load Balancer que exija autenticação.

  • Quando uma solicitação for enviada ao destino, a aplicação deverá definir a expiração como -1 para todos os cookies de autenticação. Os Application Load Balancers são compatíveis com cookies de até 16 K e, portanto, podem criar até 4 fragmentos para enviar ao cliente.

    • Se o IdP tiver um endpoint de logout, ele deverá enviar um redirecionamento para o endpoint de logout do IdP, por exemplo, o endpoint LOGOUT documentado no Guia do desenvolvedor do Amazon Cognito.

    • Se o IdP não tiver um endpoint de logout, a solicitação retornará à página inicial de logout do cliente e o processo de login será reiniciado.

  • Supondo que o IdP tenha um endpoint de logout, o IdP deverá expirar os tokens de acesso e os tokens de atualização e redirecionar o usuário de volta para a página inicial de logout do cliente.

  • As solicitações subsequentes seguirão o fluxo original de autenticação.