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 desenvolvedores da comunidade a criar seus próprios SDKs amigáveis ao usuário. Este artigo irá orientá-lo na construção de um SDK básico do lado do cliente para OIDC.
Introdução
Logto fornece a nossos desenvolvedores e grupos empresariais uma solução abrangente de Gerenciamento de Identidade e Acesso do Cliente (CIAM). Oferecemos uma ampla variedade de SDKs prontos para uso para diferentes plataformas e frameworks de aplicativos. Combinado com nosso serviço em nuvem Logto, você pode facilmente estabelecer um fluxo de autorização de usuário altamente seguro para seu aplicativo em questão de minutos. Como uma empresa que nasceu da comunidade de desenvolvedores, Logto abraça e valoriza nosso engajamento com a comunidade. Além dos SDKs oficialmente desenvolvidos pela Logto, continuamos a incentivar e acolher calorosamente os desenvolvedores da comunidade a contribuir com sua expertise criando SDKs mais diversos e amigáveis ao usuário, atendendo às necessidades únicas de várias plataformas e frameworks. Neste artigo, iremos demonstrar brevemente como implementar um SDK de autenticação padrão OIDC passo a passo.
Contexto
O fluxo do 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 um aplicativo e obtenham autorização para acesso adicional a qualquer recurso privado de forma segura. Consulte as especificações OIDC para obter mais detalhes.
Fluxo de trabalho
Um fluxo de código de autorização padrão inclui as seguintes etapas:
Fluxo de autenticação
- Usuário inicia a solicitação de login: Um usuário anônimo chega ao seu aplicativo a partir de uma entrada pública. Tenta se autenticar e talvez solicitar mais acesso a um recurso protegido em um aplicativo ou serviço de terceiros.
- Autenticação do usuário: O aplicativo do cliente gera um 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 variedade de métodos de login e é autenticado pelo servidor de autorização.
- Manusear callback de login: Após uma autenticação bem-sucedida, o usuário será redirecionado de volta ao seu aplicativo com um
authorization_code
concedido. Esteauthorization_code
contém todas as permissões relevantes vinculadas ao status de autenticação e dados de autorização solicitados. - Troca de token: Solicitar troca de token 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
: Umaccess_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 a troca contínua de umaccess_token
Fluxo de autorização
- Acessando informações do usuário: Para acessar mais informações do usuário, o aplicativo pode fazer solicitações adicionais ao endpoint UserInfo, utilizando o
access_token
opaco obtido no fluxo de troca de token inicial. Isso permite a recuperação de detalhes adicionais sobre o usuário, como seu endereço de e-mail ou foto de perfil. - Concedendo acesso ao recurso protegido: Se necessário, o aplicativo pode fazer solicitações adicionais ao endpoint de troca de token, utilizando o
refresh_token
combinado com os parâmetrosresource
escope
, para obter umaccess_token
dedicado para o usuário acessar o recurso alvo. Este processo resulta na emissão de umaccess_token
formatado JWT contendo todas as informações de autorização necessárias para acessar o recurso protegido.
Implementação
Vamos seguir algumas estratégias de design dentro do nosso SDK JavaScript @logto/client para demonstrar o processo de implementação de um SDK simples para o seu próprio aplicativo do cliente. Por favor, tenha em mente que a estrutura de código detalhada pode variar dependendo do framework do cliente com o qual você está trabalhando. Sinta-se à vontade para escolher qualquer um dos SDKs oficiais do Logto como exemplo para o seu próprio projeto SDK.
Visualização
Construtor
O construtor deve receber um logtoConfig como entrada. Isso fornece todas as configurações necessárias para você 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.
Inicializar a autenticação do usuário
Antes de gerar um 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
Definir um método privado `getOidcConfigs`` para obter as 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 endpoints e as capacidades do servidor. (Consulte OAuth OAuth Authorization Server Metadata Specs para obter mais detalhes.)
Gerador PKCE
Um fluxo de validação PKCE(Proof Key for Code Exchange) é essencial para todas as trocas de código de autorização do cliente público. Ele atenua o risco do ataque de interceptação de authorization_code. Portanto, um code_challenge
e code_verifier
são necessários para todas as solicitações de autorização de aplicações cliente público (por exemplo, aplicativo nativo e SPA).
Os métodos de implementação podem variar dependendo das linguagens e frameworks que você está usando. 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 inter-sites (CSRF).
Armazenar informações da sessão intermediária
Existem vários parâmetros que precisam ser preservados no armazenamento para fins de validação depois que o usuário se autenticar e for redirecionado de volta ao lado do cliente. Vamos implementar um método para definir esses parâmetros intermediários no armazenamento.
Login
Vamos reunir tudo implementado acima, definir um método que gera um URL de login do usuário e redireciona o usuário para o servidor de autorização para se autenticar.
Lidar com o callback de login do usuário
Na seção anterior, criamos um método de login que gera uma URL para a autenticação do usuário. Esta URL contém todos os parâmetros necessários necessários para iniciar um fluxo de autenticação a partir de um aplicativo 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 carregados no redirect_uri para completar os seguintes fluxos de troca de token.
Extrair e verificar o URL de callback
Esta etapa de validação é extremamente importante para prevenir qualquer forma de ataque forjado ao callback de autorização. O URL de callback DEVE ser cuidadosamente verificado antes de enviar uma solicitação de troca de código adicional ao servidor de autorização. Primeiramente, precisamos recuperar os dados de signInSession que armazenamos do armazenamento do aplicativo.
Então verifique o parâmetro URL do callback antes de enviar a solicitação de troca de token.
- Use o
redirectUri
armazenado previamente para verificar se ocallbackUri
é o mesmo que enviamos para o servidor de autorização. - Use o
state
armazenado previamente para verificar se o estado retornado é o mesmo 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, usaremos 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, consulte a especificação de troca de token.
- code: o
authorization_code
que recebemos do URI de callback - clientId: o ID do aplicativo
- redirectUri: O mesmo valor é usado ao gerar a URL de login para o usuário.
- codeVerifier: verificador de código PKCE. Semelhante ao redirectUri, o servidor de autorização irá comparar este valor com o que enviamos anteriormente, garantindo a validação da solicitação de troca de token de entrada.
Lidar com callback de login
Agrupando tudo o que temos. Vamos construir o método de manipulação do callback de login:
Como resultado, a solicitação de troca de token retornará os seguintes tokens:
id_token
: OIDC idToken, um Token Web JSON (JWT) que contém informações de identidade sobre o usuário autenticado. id_token também pode ser usado como a Única Fonte 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 informações 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 o aplicativo do cliente obtenha um novo access_token sem exigir que o usuário se reautentique, concedendo acesso a longo prazo aos recursos.expires_in
: A duração do tempo, em segundos, para a qual o access_token é válido antes de expirar.
Verificação do token ID
Verificar e extrair alegações do id_token
é uma etapa crucial no processo de autenticação para garantir a autenticidade e integridade do token. Aqui estão as principais etapas envolvidas na verificação de um idToken
.
- Verificação da assinatura: O
id_token
é assinado digitalmente pelo servidor de autorização usando sua chave privada. O aplicativo do 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 que foi realmente emitido pelo servidor de autorização legítimo. - Verificação do emissor**:** Verifique se a alegação "iss" (emissor) no
id_token
corresponde ao valor esperado, indicando que o token foi emitido pelo servidor de autorização correto. - Verificação de público: Certifique-se de que a alegação "aud" (público) no
id_token
corresponde ao ID do cliente do aplicativo do cliente, garantindo que o token seja destinado ao cliente - Verificação de expiração: Verifique se a alegação "iat" (emitido em) no
id_token
não passou do tempo atual, garantindo que o token ainda seja válido. Como há custos de transação de rede, precisamos definir uma tolerância de tempo emitida ao validar a alegação iat do token recebido.
O id_token retornado é um Token Web JSON (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, vamos utilizar 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 obtidas do id_token
OIDC emitido pelo servidor de autorização. No entanto, por razões de desempenho, o conteúdo do token JWT é limitado. Para obter informações de perfil de usuário mais detalhadas, os servidores de autorização compatíveis com OIDC oferecem um endpoint de informações do usuário fora da caixa. Este endpoint permite que você recupere dados adicionais do perfil do usuário solicitando escopos específicos do perfil do usuário.
Ao chamar um endpoint de troca de token sem indicar um recurso de API específico, por padrão, o servidor de autorização emitirá um access_token
do tipo opaco. Este access_token
só pode ser usado para acessar o endpoint de informações 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, um aplicativo cliente não só requer autenticação do 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 particulares. Isso nos permite obter acesso a essas APIs protegidas.
Resumo
Fornecemos implementações de métodos essenciais para o processo de autenticação e autorização do usuário no aplicativo do lado do cliente. Dependendo do seu cenário específico, você pode organizar e otimizar a lógica do SDK de acordo. Lembre-se de que podem existir variações devido a diferentes plataformas e frameworks.
Para obter detalhes adicionais, explore os pacotes SDK oferecidos pela Logto. Incentivamos mais usuários a se juntarem ao desenvolvimento e a se envolverem em discussões conosco. Seus feedback e contribuições são altamente valorizados à medida que continuamos a aprimorar e expandir as capacidades do SDK.
Apêndice
Escopos reservados
Escopos reservados do Logto que você precisará passar durante a solicitação de autenticação inicial. Esses escopos são ou OIDC-reservados ou Logto-reservados para completar um fluxo de autorização bem-sucedido.
Nome do escopo | Descrição |
---|---|
openid | Necessário para conceder id_token após uma autenticação bem-sucedida. |
offline-access | Necessário para conceder um refresh_token que permite que seu aplicativo cliente troque e renove um access_token fora da tela. |
profile | Necessário para obter acesso às informações básicas do usuário |
Logto Config
Nome da propriedade | Tipo | Requerido | Descrição | Valor padrão |
---|---|---|---|---|
appId | string | verdadeiro | O identificador de aplicação único. Gerado pelo servidor de autorização para identificar o aplicativo cliente. | |
appSecret | string | O segredo do aplicativo é usado, juntamente com o ID do aplicativo, para verificar a identidade do solicitante. É necessário para clientes confidenciais como aplicativos web Go ou Next.js, e opcional para clientes públicos como aplicativos nativos ou aplicativos de página única (SPAs) | ||
endpoint | string | verdadeiro | Seu endpoint raiz do servidor de autorização. Esta propriedade será amplamente usada para gerar solicitações de autorização.endpoint. | |
scopes | lista de strings | Indica todos os escopos de recurso necessários que o usuário pode precisar ser concedidos para acessar quaisquer recursos protegidos dados. | [reservedScopes] | |
resources | lista de strings | Todos os indicadores de recurso protegido que o usuário pode solicitar acesso |