Português (Portugal)
  • SDK
  • OIDC

Implemente um SDK OIDC simples do lado do cliente

Logto oferece uma variedade de SDKs para diferentes plataformas. Além de nossos SDKs oficiais, incentivamos os desenvolvedores da comunidade a criar seus próprios SDKs amigáveis ao usuário. Este artigo irá guiá-lo na construção de um SDK básico do lado do cliente para OIDC.

Simeng
Simeng
Developer

Introdução

Logto fornece aos nossos desenvolvedores e grupos de negócios uma solução abrangente de gerenciamento de identidade e acesso do cliente (CIAM). Oferecemos uma ampla gama de SDKs prontos para uso para diferentes plataformas e frameworks de aplicação. Combinado com nosso serviço Logto na nuvem, você pode estabelecer sem esforço um fluxo de autorização de usuário altamente seguro para sua aplicação em questão de minutos. Como uma empresa que nasceu da comunidade de desenvolvedores, a Logto abraça e valoriza nosso engajamento com a comunidade. Além dos SDKs oficialmente desenvolvidos pela Logto, nós continuamente incentivamos e recebemos calorosamente os desenvolvedores da comunidade para contribuírem com sua experiência criando SDKs mais diversos e amigáveis ao usuário, atendendo às necessidades únicas de várias plataformas e estruturas. Neste artigo, vamos demonstrar brevemente como implementar um SDK de autenticação padrão OIDC passo a passo.

Contexto

O fluxo OpenID Connect (OIDC) é um protocolo de autenticação que se baseia no framework OAuth 2.0 para fornecer verificação de identidade e capacidades de single sign-on. Ele permite que os usuários se autentiquem com uma aplicação e obtenham autorização para acessar de forma segura quaisquer recursos privados. Por favor, consulte as especificações OIDC para mais detalhes.

Fluxo de trabalho

Um fluxo de código de autorização padrão inclui as seguintes etapas:

Fluxo de autenticação

  1. Usuário inicia a solicitação de autenticação: Um usuário anônimo chega à sua aplicação a partir de uma entrada pública. Tenta se autenticar e talvez faça uma solicitação adicional para acessar um recurso protegido em uma aplicação ou serviço de terceiros.
  2. Autenticação do usuário: A aplicação cliente gera uma URI de autenticação e envia uma solicitação para o servidor de autorização, que redireciona o usuário para sua página de login. O usuário interage com a página de login usando uma ampla gama de métodos de login e é autenticado pelo servidor de autorização.
  3. Tratar o retorno do login: Após uma autenticação bem sucedida, o usuário será redirecionado de volta para sua aplicação com um authorization_code concedido . Este authorization_code contém todas as permissões relevantes ligadas ao status de autenticação e aos dados de autorização solicitados.
  4. Troca de tokens: Solicita a troca de tokens usando o authorization_code extraído do endereço de redirecionamento acima. Em retorno:
    • id_token: Um JWT assinado digitalmente que contém informações de identidade sobre o usuário autenticado.
    • access_token: Um access_token opaco que pode ser usado para acessar o endpoint de informações básicas do usuário.
    • refresh_token: Token de credencial que permite ao usuário manter uma troca contínua por um access_token

Fluxo de autorização

  1. Acessar informações do usuário: Para acessar mais informações do usuário, a aplicação pode fazer solicitações adicionais ao endpoint UserInfo, utilizando o access_token opaco obtido no fluxo de troca de tokens inicial. Isso permite a recuperação de detalhes adicionais sobre o usuário, como seu endereço de email ou foto do perfil.
  2. Conceder acesso ao recurso protegido: Se necessário, a aplicação pode fazer solicitações adicionais ao endpoint de troca de token, utilizando o refresh_token combinado com os parâmetros resource e scope, para obter um access_token dedicado para o usuário acessar o recurso alvo. Este processo resulta na emissão de um access_token formatado como JWT contendo todas as informações de autorização necessárias para acessar o recurso protegido.

Implementação

Seguiremos algumas estratégias de design dentro de nosso SDK JavaScript @logto/client para demonstrar o processo de implementação de um SDK simples para sua própria aplicação cliente. Por favor, tenha em mente que a estrutura de código detalhada pode variar dependendo do framework cliente com o qual você está trabalhando. Sinta-se à vontade para escolher qualquer um dos SDKs oficiais do Logto como exemplo para seu próprio projeto de SDK.

Previsualização

Construtor

O construtor deve receber um logtoConfig como entrada. Isso fornece todas as configurações necessárias que você precisará para estabelecer uma conexão de autenticação através deste SDK.

Dependendo da plataforma ou framework que você está usando para o SDK, você pode passar uma instância de armazenamento local persistente para o construtor. Esta instância de armazenamento será usada para armazenar todos os tokens e segredos relacionados à autorização.

Iniciar autenticação do usuário

Antes de gerar uma URL de solicitação de autenticação, é essencial concluir várias etapas de preparação para garantir um processo seguro.

Obter configurações OIDC do servidor de autorização

Defina um método privado `getOidcConfigs`` para buscar configurações OIDC do endpoint de descoberta do servidor de autorização. A resposta das configurações OIDC contém todas as informações de metadados que o cliente pode usar para interagir com o servidor de autorização, incluindo suas localizações de endpoint e as capacidades do servidor. (Por favor, consulte OAuth OAuth Authorization Server Metadata Specs para mais detalhes.)

Gerador PKCE

Um fluxo de validação PKCE(Proof Key for Code Exchange) é essencial para todos os fluxos de troca de código de autorização do cliente público. Ele mitiga o risco de ataque de interceptação de authorization_code. Assim, um code_challenge e code_verifier é necessário para todas as solicitações de autorização do cliente público(aplicações nativas e SPAs).

Os métodos de implementação podem variar dependendo das linguagens e frameworks que você está usando. Por favor, consulte a especificação code_challenge e code_verifier para as definições detalhadas.

Gerar parâmetro state

No fluxo de autorização, o parâmetro state é um valor gerado aleatoriamente que é incluído na solicitação de autorização enviada pelo cliente. Ele atua como uma medida de segurança para prevenir ataques de falsificação de solicitação entre sites (CSRF).

Armazenar informações da sessão intermediária

Existem vários parâmetros que precisam ser preservados no armazenamento para validação após o usuário se autenticar e ser redirecionado de volta para o lado do cliente. Vamos implementar um método para definir esses parâmetros intermediários no armazenamento.

Login

Vamos envolver tudo o que foi implementado acima, definir um método gerando uma URL de login do usuário e redirecionar o usuário para o servidor de autorização para se autenticar.

Lidar com o retorno do login do usuário

Na seção anterior, criamos um método de login que gera uma URL para autenticação do usuário. Esta URL contém todos os parâmetros necessários para iniciar um fluxo de autenticação a partir de uma aplicação cliente. O método redireciona o usuário para a página de login do servidor de autorização para autenticação. Após um login bem sucedido, o usuário final será redirecionado de volta para a localização de redirect_uri fornecida acima. Todos os parâmetros necessários serão transportados no redirect_uri para completar os fluxos de troca de tokens subsequentes.

Extrair e verificar a URL de retorno

Esta etapa de validação é extremamente importante para prevenir qualquer forma de ataques de retorno de autorização forjados. A URL de retorno DEVE ser cuidadosamente verificada antes de enviar uma solicitação de troca de código adicional ao servidor de autorização. Primeiro de tudo, precisamos recuperar os dados signInSession que armazenamos do armazenamento do aplicativo.

Então verifique os parâmetros da URL de retorno antes de enviar a solicitação de troca de token.

  • Use o redirectUri armazenado anteriormente para verificar se o callbackUri é o mesmo que o que enviamos para o servidor de autorização.
  • Use o state armazenado anteriormente para verificar se o state retornado é o mesmo que o que enviamos para o servidor de autorização.
  • Verifique se há algum erro retornado pelo servidor de autorização
  • Verifique a existência do authorization_code retornado

Enviar a solicitação de troca de código

Como a etapa final do fluxo de autenticação do usuário, utilizaremos o authorization_code retornado para enviar uma solicitação de troca de token e obter os tokens de autorização necessários. Para mais detalhes sobre as definições dos parâmetros da solicitação, por favor, consulte a especificação de troca de token.

  • code: o authorization_code que recebemos da URI de retorno
  • clientId: o ID da aplicação
  • redirectUri: O mesmo valor é usado ao gerar a URL de login para o usuário.
  • codeVerifier: verificador de código PKCE. Similar ao redirectUri, o servidor de autorização irá comparar este valor com o que nós enviámos anteriormente, garantindo a validação da solicitação de troca de token que está chegando.

Lidar com o retorno do login

Envolver tudo o que temos. Vamos construir o handle método signInCallback :

Como resultado, a solicitação de troca de token retornará os seguintes tokens:

  • id_token: OIDC idToken, um JWT (JSON Web Token) que contém informações de identidade sobre o usuário autenticado. O id_token também pode ser usado como a Fonte Única de Verdade (SSOT) do status de autenticação de um usuário.
  • access_token: O código de autorização padrão retornado pelo servidor de autorização. Pode ser usado para chamar o endpoint de info do usuário e recuperar informações do usuário autenticado.
  • refresh_token: (se o escopo offline_access estiver presente na solicitação de autorização): Este token de atualização permite que a aplicação cliente obtenha um novo access_token sem requerer que o usuário re-autentique, concedendo acesso de longo prazo aos recursos.
  • expires_in: A duração do tempo, em segundos, para qual o access_token é válido antes de expirar.

Verificação do token ID

Verificar e extrair reivindicações do id_token é uma etapa crucial no processo de autenticação para garantir a autenticidade e integridade do token. Aqui estão as etapas-chave envolvidas na verificação de um idToken.

  • Verificação de Assinatura: O id_token é assinado digitalmente pelo servidor de autorização usando sua chave privada. A aplicação cliente precisa validar a assinatura usando a chave pública do servidor de autorização. Isso garante que o token não foi adulterado e foi de fato emitido pelo servidor de autorização legítimo.
  • Verificação do Emitente:: Verifique se a reivindicação "iss" (emissor) no id_token corresponde ao valor esperado, indicando que o token foi emitido pelo servidor de autorização correto.
  • Verificação do público: Garanta que a reivindicação "aud" (público) no id_token corresponde ao ID do cliente da aplicação cliente, garantindo que o token é destinado ao cliente.
  • Checagem de expiração: Verifique se a reivindicação "iat" (emitida em) no id_token não passou do horário atual, garantindo que o token ainda é válido. Como há custos de transação de rede, precisamos definir uma tolerância de tempo de emissão ao validar a reivindicação iat do token recebido.

O id_token retornado é um JSON Web Token (JWT) padrão. Dependendo do framework que você está usando, você pode encontrar vários plugins convenientes de validação de tokens JWT para auxiliar na decodificação e validação do token. Para este exemplo, utilizaremos jose em nosso SDK JavaScript para facilitar a validação e decodificação do token.

Obter informações do usuário

Após a autenticação bem sucedida do usuário, as informações básicas do usuário podem ser recuperadas do id_token OIDC emitido pelo servidor de autorização. No entanto, devido a considerações de performance, o conteúdo do token JWT é limitado. Para obter mais detalhes do perfil do usuário, os servidores de autorização compatíveis com OIDC oferecem um endpoint de info do usuário pronto para uso. Este endpoint permite que você recupere dados adicionais do perfil do usuário ao solicitar scopes específicos do perfil do usuário.

Ao chamar um endpoint de troca de token sem indicar um recurso API específico, o servidor de autorização emitirá, por padrão, um access_token do tipo opaco. Este access_token só pode ser usado para acessar o endpoint de info do usuário, permitindo a recuperação de dados básicos do perfil do usuário.

Obter token de acesso para autorização de recurso protegido

Na maioria dos casos, uma aplicação cliente não só requer autenticação de usuário, mas também precisa de autorização do usuário para acessar certos recursos protegidos ou endpoints de API. Aqui, usaremos o refresh_token obtido durante o login para adquirir access_token(s) especificamente concedidos para gerenciar recursos específicos. Isso nos permite obter acesso às APIs protegidas.

Resumo

Nós fornecemos implementações essenciais do método para o processo de autenticação e autorização do usuário do aplicativo do lado do cliente. Dependendo do seu cenário específico, você pode organizar e otimizar a lógica do SDK de acordo. Por favor, note que podem existir variações devido a diferentes plataformas e frameworks.

Para detalhes adicionais, explore os pacotes de SDK oferecidos pela Logto. Incentivamos mais usuários a se juntar ao desenvolvimento e participar de discussões conosco. Seu feedback e contribuições são altamente valorizados à medida que continuamos aprimorar e expandir as capacidades do SDK.

Apêndice

Reserved scopes

Os escopos reservados Logto que você precisará passar durante a solicitação de autenticação inicial. Esses escopos são fundamentais reservados pela OIDC ou Logto para completar um fluxo de autorização bem sucedido.

Nome do EscopoDescrição
openidReqxaderido para conceder id_token após uma autenticação bem sucedida.
offline-accessRequerido para conceder um refresh_token que permite à sua aplicação cliente trocar e renovar um access_token fora da tela.
profileRequerido para obter acesso às informações básicas do usuário

Logto Config

Nome da propriedadeTipoRequeridoDescriçãoValor Padrão
appIdstringtrueO identificador único da aplicação. Gerado pelo servidor de autorização para identificar a aplicação cliente.
appSecretstringO segredo da aplicação é usado, junto com o ID da aplicação, para verificar a identidade do solicitante. É requerido para clientes confidenciais como aplicações web Go ou Next.js, e opcional para clientes públicos como aplicações nativas ou aplicações de página única (SPAs)
endpointstringtrueSeu endpoint raiz do servidor de autorização. Esta propriedade será amplamente usada para gerar solicitações de autorização.
scopesstring listIndica todos os escopos de recurso necessários que o usuário pode precisar para ser concedido a fim de acessar qualquer recurso protegido dado.[reservedScopes]
resourcesstring listTodos os indicadores de recurso protegido que o usuário pode solicitar acesso

Util methods

generateRandomString