Amazon Cognito e Últimas Especificações OAuth/OIDC

Introdução

"Amazon Cognito os pools de usuários implementam tokens de identificação, acesso e atualização definidos pelo padrão aberto OpenID Connect (OIDC) “ — trecho de “Usando tokens com userpools

No entanto, como a implementação do OIDC da Cognito é muito limitada e inflexível, é comum que a implementação do OIDC da Cognito não possa satisfazer os requisitos do seu sistema. Por exemplo, o algoritmo de assinatura de tokens de ID emitidos pela Cognito é RS256 e não há nenhuma maneira de mudá-lo, embora o algoritmo é proibido por API de grau financeiro (FAPI), por razões de segurança.

Este tutorial explica como usar o Cognito apenas como um banco de dados de usuários e delegar tarefas relacionadas ao OAuth/OIDC para Authlete para que seu sistema possa continuar a usar o Cognito e, ao mesmo tempo, suportar as especificações mais recentes do OAuth/OIDC, como a API de grau financeiro (cf). Folha de especificações authlete).

Arquitetura

No contexto OAuth 2.0, um servidor que emite access token (e opcionalmente refresh token) é chamado servidor de autorização. Por outro lado, no contexto OpenID Connect, um servidor que emite ID token é chamado Provedor OpenID (Idp). Como o OIDC foi definido intencionalmente em cima do OAuth 2.0, é comum que um servidor tenha ambas as funções. Portanto, o mesmo servidor pode ser diferentemente chamado de “servidor de autorização” ou “IdP” dependendo dos contextos. Este tutorial refere-se ao servidor como “servidor de autorização” uniformemente.

Para apoiar o fluxo de código de autorização (RFC 6749 Seção 4.1), que é o fluxo mais comum no OAuth/OIDC, um servidor de autorização tem que implementar dois pontos finais. Eles são chamados endpoint de autorização (RFC 6749 Seção 3.1) e ponto final token (RFC 6749 Seção 3.2). O Cognito User Pool fornece implementações dos dois pontos finais, mas você precisa implementar seus próprios pontos finais personalizados quando a implementação do OIDC da Cognito não for satisfatória.

O diagrama abaixo ilustra a relação entre os componentes no fluxo de código de autorização quando Cognito e Authlete são usados combinados.


Authorization Code Flow by Cognito and Authlete

O ponto no diagrama é que a autenticação do usuário é realizada pela Cognito, mas as tarefas relacionadas ao OAuth/OIDC são delegadas ao Authlete. Considerando o fato de que a especificação central do OAuth 2.0 (RFC 6749) afirma “A forma como o servidor de autorização autentica o proprietário de recursos (por exemplo, nome de usuário e login de senha, cookies de sessão) é além do escopo desta especificação.”, essa separação clara traz muito mais benefícios do que a abordagem em que uma solução de gerenciamento de usuário suporta diretamente o OAuth/OIDC.

As seções a seguir descrevem detalhadamente o que o servidor de autorização preparado para este tutorial faz em suas implementações do ponto final de autorização e do ponto final do token.

Endpoint de autorização

O ponto final de autorização no servidor de autorização de amostra:

  1. aceita um solicitação de autorização (RFC 6749 Seção 4.1.1), a partir de um aplicativo cliente através de um navegador web,
  2. extrai os parâmetros de consulta da solicitação de autorização,
  3. passa os parâmetros de consulta extraídos para Authlete /api/auth/autorização API
  4. constrói um página de autorização com base nas informações devolvidas da API Authlete,
  5. envia a página de autorização de volta para o navegador da Web,
  6. obtém o nome de usuário e senha do usuário através do formulário de login incorporado na página de autorização,
  7. passa o nome de usuário e senha para Cognito AdministradorAuth API para autenticar o usuário,
  8. passa o nome de usuário para Cognito AdminGetUser API para obter atributos do usuário,
  9. passa o assunto do usuário (identificador exclusivo) e atributos do usuário para Authlete /api/auth/authorization/issue API
  10. constrói um resposta de autorização (RFC 6749 Seção 4.1.2), com base nas informações devolvidas da API Authlete, e
  11. envia a resposta de autorização para o navegador da Web.

Ponto final do token

O ponto final do token no servidor de autorização de amostra:

  1. aceita um solicitação de token (RFC 6749 Seção 4.1.3), a partir de um aplicativo de cliente,
  2. extrai os parâmetros de formulário da solicitação de token,
  3. passa os parâmetros de formulário extraídos para Authlete /api/auth/token API
  4. constrói um resposta token (RFC 6749 Seção 4.1.4), com base nas informações devolvidas da API Authlete, e
  5. envia a resposta de token para o aplicativo do cliente.

Implementação

A arquitetura explicada acima é implementada em django-oauth-servidor, que é um servidor de autorização de código aberto escrito em Python com o Django estrutura web. Para executar o servidor, siga os passos abaixo.

Configuração Cognito

  1. Crie um pool de usuários do Cognito. Certifique-se de que o email atributo está incluído porque usaremos o atributo mais tarde para testes.
  2. Adicione um cliente ao pool de usuários cognito e habilite ALLOW_ADMIN_USER_PASSWORD_AUTH na seção “Configuração de fluxos de auth” da configuração do cliente para que o cliente possa usar o “Fluxo de autenticação do lado do servidor”.
  3. Adicione um usuário ao pool de usuários do Cognito.
  4. Certifique-se de que sua conta AWS tenha permissões neccesary para chamar Cognito AdministradorAuth API e AdminGetUser API.

Servidor de autorização de configuração

Instale bibliotecas Python necessárias.

$ pip install authlete           # Authlete Library for Python
$ pip install authlete-django    # Authlete Library for Django
$ pip install boto3              # AWS SDK for Python

Baixe o código-fonte da implementação do servidor de autorização.

$ git clone https://github.com/authlete/django-oauth-server.git
$ cd django-oauth-server

Editar o arquivo de configuração Authlete (authlete.ini), para acessar APIs Authlete.

$ vi authlete.ini

Abra o arquivo de configuração Django (django_oauth_server/settings.py),

$ vi django_oauth_server/settings.py

e adicionar backends.CognitoBackend Para AUTHENTICATION_BACKENDS. Veja “Especificando backends de autenticação” em “Personalização da autenticação em Django” para detalhes sobre a autenticação django backends.

AUTHENTICATION_BACKENDS = ('backends.CognitoBackend',)

Além disso, editar COGNITO_USER_POOL_ID e COGNITO_CLIENT_ID no mesmo arquivo corretamente.

COGNITO_USER_POOL_ID = 'YOUR_COGNITO_USER_POOL_ID'
COGNITO_CLIENT_ID    = 'YOUR_COGNITO_CLIENT_ID'

Se você está interessado em como chamar Cognito AdministradorAuth API e AdminGetUesr API, olhe para o código fonte cognito_backend.py.

Iniciar servidor de autorização

Para iniciar o servidor de autorização, digite o comando abaixo.

$ python manage.py runserver

make run” faz a mesma coisa.

$ make run

O servidor de autorização expõe alguns pontos finais conforme listado na tabela abaixo. Uma maneira fácil de confirmar essa configuração Authlete (authlete.ini) está correto é acessar o ponto final de descoberta (http://localhost:8000/.well-known/openid-configuration) e ver se ele retorna JSON em conformidade com OpenID Connect Discovery 1.0.

Endpoint URL
Endpoint de Autorização http://localhost:8000/api/authorization
Endpoint de Token http://localhost:8000/api/token
Discovery Endpoint http://localhost:8000/.well-known/openid-configuration

Teste

Fizemos toda a preparação. Vamos obter um token de acesso e um token de ID pelo fluxo de código de autorização.

Solicitação de Autorização

No fluxo de código de autorização, o primeiro passo é enviar um solicitação de autorização para o endpoint de autorização do servidor de autorização através de um navegador web. Neste tutorial, o ponto final de autorização é http://localhost:8000/api/authorization hospedado no servidor django-oauth. Substituir CLIENT_ID e REDIRECT_URI na URL abaixo (que representa uma solicitação de autorização) corretamente e acesse a URL com seu navegador web.

http://localhost:8000/api/authorization?response_type=code&client_id=CLIENT_ID&scope=openid+email&state=123&nonce=abc&redirect_uri=REDIRECT_URI

Seu navegador da Web exibirá um página de autorização gerado pelo servidor de autorização. Vai parecer lá embaixo.


Authorization page in authorization code flow

A página tem campos de entrada para ID de login e senha. Insira o nome de usuário e a senha do usuário que você adicionou ao pool de usuários do Cognito lá e pressione o botão “Autorizar” e seu navegador da Web será redirecionado para o ponto final de redirecionamento do aplicativo do cliente.

A URL do ponto final de redirecionamento que você pode ver na barra de endereço do seu navegador contém code parâmetro de resposta como abaixo.

REDIRECT_URI?state=123&code=RwRq2Lp0bJVMiLPKAFz4qB1hxieBD1X5HKuv8EPkJeM

O valor de code parâmetro de resposta é o código de autorização que foi emitido do servidor de autorização para o aplicativo do seu cliente. O código de autorização é necessário quando o aplicativo do cliente faz uma solicitação de token.

Solicitação de token

Depois de obter um código de autorização, o aplicativo do cliente envia um solicitação de token para o ponto final token do servidor de autorização. Neste tutorial, o ponto final do token é http://localhost:8000/api/token hospedado no servidor django-oauth.

Uma solicitação de token pode ser feita por curl comando em um terminal shell. Abaixo está um exemplo de solicitação de token. Não se esqueça de substituir CLIENT_ID, REDIRECT_URI e CODE com os valores reais antes de digitar.

$ curl http://localhost:8000/api/token -d grant_type=authorization_code -d client_id=CLIENT_ID -d redirect_uri=REDIRECT_URI -d code=CODE
Argumento Descrição
http://localhost:8000/api/token A URL do ponto final do token.
-d grant_type=authorization_code indica que o fluxo é o fluxo de código de autorização.
-d client_id=CLIENT_ID especifica o ID do cliente. CLIENT_ID com a ID do cliente real do seu aplicativo de cliente.
-d redirect_uri=REDIRECT_URI especifica o URI redirecionado. Substituir REDIRECT_URI com o mesmo valor dado na solicitação de autorização.
-d code=CODE especifica o código de autorização. Substituir CODE com o código de autorização real.

Quando a solicitação de token é bem sucedida, o ponto final do token retorna JSON que inclui access_token e id_token Como abaixo.

{
  "access_token": "FrGIJQpW51-l5mYJHcqGUNIKGJ1W23fFlW6c9AQEZEc",
  "refresh_token": "jhvKm9-haLQwnIR4CfkL6bfPIBBlqluFeqZKAgdPNjM",
  "scope": "email openid",
  "id_token": "eyJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6InRha2FAYXV0aGxldGUuY29tIiwiaXNzIjoiaHR0cHM6Ly9leGFtcGxlLmNvbSIsInN1YiI6IjIiLCJhdWQiOlsiNDMyNjM4NTY3MCJdLCJleHAiOjE2MTY0MTI3NDIsImlhdCI6MTYxNjMyNjM0MiwiYXV0aF90aW1lIjoxNjE2MzI2MTAwLCJub25jZSI6ImFiYyIsInNfaGFzaCI6InBtV2tXU0JDTDUxQmZraG43OXhQdUEifQ.7sXy2FcELxHo3LCQkb9teLaUE9jtRxXsa8diJKnkwAo",
  "token_type": "Bearer",
  "expires_in": 86400
}

O valor de access_token é o token de acesso emitido. Da mesma forma, o valor de id_token é o token de ID emitido.

A parte útil do token de ID emitido neste tutorial é decodificada da seguinte forma. Podemos confirmar que o servidor de autorização se comunicou com o grupo de usuários Congnito com sucesso, verificando se o valor de email na carga corresponde ao email atributo do usuário no pool de usuários Cognito.

{
  "email": "taka@authlete.com",
  "iss": "https://example.com",
  "sub": "2",
  "aud": [
    "4326385670"
  ],
  "exp": 1616412742,
  "iat": 1616326342,
  "auth_time": 1616326100,
  "nonce": "abc",
  "s_hash": "pmWkWSBCL51Bfkhn79xPuA"
}

Parabéns!

Você completou este tutorial e aprendeu como ativar seu servidor de autorização para usar o Amazon Cognito como um banco de dados de usuário e, ao mesmo tempo, suportar as especificações mais recentes do OAuth/OIDC usando o Authlete.

Entre em contato conosco se você precisar de apoio. Você é sempre bem-vindo!