Suporte para tokens jwt anônimos no IdentityServer4 usando AnonymousIdentity


Recentemente, eu precisava implementar o suporte à autenticação de usuário anônimo com base no OpenId Connect e OAuth 2.0 na plataforma ASP.NET Core. A especificação desses protocolos não será explicada aqui, pois existem artigos completos sobre o Habr. Vamos direto ao ponto.


Por que precisamos de um token anônimo? Para autorizar um usuário anônimo em um recurso de API, especialmente na arquitetura de microsserviços, ele também pode alterar o estado de nosso aplicativo, por exemplo, Vasya gostava de uma camiseta com gatos, adicionava-a à cesta da loja online e, possivelmente, fazia um pedido como hóspede. Para entender que era Vasily, o token anônimo contém o identificador do usuário anônimo e o identificador da sessão. Quando o Vasily efetua login, esses parâmetros serão incluídos no token autenticado.


Além disso, um token de acesso anônimo pode conter quaisquer declarações (ou reivindicações) adicionais.


As ferramentas



Implementação


O IdentityServer4 tem muitos exemplos no GitHub.


Adicionar suporte para tokens anônimos é bastante simples:


  • Instale AnonymousIdentity em um projeto com IdneitityServer4
    Install-Package AnonymousIdentity 
  • Registrar AnonymousIdentity em Startup.cs
     services.AddIdentityServer() //   .AddAnonymousAuthentication(); 

Cenário de interação


Considere obter um token anônimo para fluxo implícito e fluxo de código de autorização .


Solicitação de ponto de autorização


Para seguir a especificação, uma solicitação de um ponto de autorização para o fluxo implícito é a seguinte.


 GET /connect/authorize? client_id=client1& scope=openid email api1& response_type=id_token token& redirect_uri=https://myapp/callback& state=abc& nonce=xyz& acr_values=0& response_mode=json 

Para o fluxo de código de autorização, uma solicitação semelhante com response_type = code (PKCE é opcional).


As diferenças entre uma solicitação regular e anônima em dois parâmetros:


  • O parâmetro acr_values ​​= 0 indica o logon anônimo. Se estiver interessado, você pode ler a especificação do OpenId Connect .
  • O parâmetro response_mode = json é usado para responder na forma de Json sem redirecionamentos desnecessários.

Recebendo token


Dependendo do status da autenticação, um token anônimo ou autenticado é retornado.


Fluxo implícito


Nesse caso, o ponto de autorização responde na forma de Json, incluindo o token de acesso.


 { "id_token": <id_token>, "access_token": <access_token>, "token_type": "Bearer", "expires_in": "2592000", "scope": "openid email api1", "state": "abc", "session_state": <optional> } 

Fluxo do código de autorização


Com essa abordagem, o ponto de autorização responde na forma de Json, incluindo o código de autorização.


 { "code": <authorization_code>, "scope": "openid email api1", "state": "abc", "session_state": <optional> } 

Em seguida, você precisa trocar o código pelo token usando o método padrão.


Nós formamos uma solicitação para o ponto final do token.


 POST /connect/token client_id=client2& client_secret=secret& grant_type=authorization_code& code=`& redirect_uri=https://myapp/callback 

Como resultado, o terminal do token responde na forma de Json, incluindo o token de acesso.


 { "id_token": <id_token>, "access_token": <access_token>, "token_type": "Bearer", "expires_in": "2592000", "scope": "openid email api1" } 

Comparando tokens anônimos e autenticados


Se o servidor de autorização não contiver dados de autenticação, obteremos um token anônimo.


 { "nbf": 1566849147, "exp": 1569441147, "iss": "https://server", "aud": [ "https://server/resources", "api" ], "client_id": "client1", "sub": "abda9006-5991-4c90-a88c-c96764027347", "auth_time": 1566849147, "idp": "local", "ssid": "9e6453dbaf5ffdb03f08812f759d3cdf", "scope": [ "openid", "email", "api1" ], "amr": [ "anon" ] } 

Você pode determinar que o usuário é anônimo usando o método de autenticação (amr).
O identificador da sessão "geral" (ssid) e o identificador do assunto (sub) serão incluídos no token autenticado, no logon do usuário subsequente.


Caso o usuário esteja logado, obtemos um token autenticado.


 { "nbf": 1566850295, "exp": 1566853895, "iss": "https://server", "aud": [ "https://server/resources", "api" ], "client_id": "client1", "sub": "bob", "auth_time": 1566850295, "idp": "local", "aid": "abda9006-5991-4c90-a88c-c96764027347", "ssid": "9e6453dbaf5ffdb03f08812f759d3cdf", "scope": [ "openid", "email", "api1" ], "amr": [ "pwd" ] } 

Como você pode ver, o identificador do usuário anônimo (aid) corresponde ao sub do token anônimo, assim como ssid. Se o cliente não iniciou o logon anônimo, o token autenticado conterá apenas ssid.


Assim, podemos autorizar um usuário anônimo e identificar suas ações após entrar no sistema.


Conclusão


Neste artigo, examinamos um cenário para obter um token anônimo / autenticado usando o IdentityServer4 com a extensão AnonymousIdentity .


Se você tiver dúvidas, terei prazer em respondê-las nos comentários.

Source: https://habr.com/ru/post/pt466467/


All Articles