Explorando concessões OIDC: Comprehendendo e resolvendo o erro "invalid_grant"
Aprenda os fundamentais das concessões OpenID Connect (OIDC), e como identificar o erro "invalid_grant".
Background
Na nossa comunidade, costumamos receber frequentemente a mesma pergunta de nossos utilizadores: Qual o problema com o erro "invalid_grant" no Logto? Tal como #503
Esse é um desafio comum e um bloqueador para alguns de nossos utilizadores quando integram o Logto nas suas próprias aplicações. No entanto, as razões por detrás deste erro variam de caso para caso, e por vezes é difícil de explicar com o contexto limitado fornecido. Assim, entender o conceito exato de OIDC e aprender como resolver o problema é essencial para todos.
Agora vamos aprofundar-nos nos fundamentos das concessões OIDC.
Concessões OIDC explicadas
Como já introduzimos num post no blog, OpenID Connect (OIDC) é um protocolo construído em cima de OAuth 2.0.
No contexto de OIDC ou OAuth2, uma concessão é um conjunto de permissões concedidas pelo proprietário do recurso (habitualmente o utilizador) a uma aplicação cliente. As concessões são essenciais para a aplicação cliente aceder às informações de identidade do utilizador e a outros recursos protegidos. OIDC define vários tipos de concessões, cada uma adequada para um cenário diferente e a maneira como uma aplicação obtém um token de acesso.
Aqui tem uma analogia para ajudá-lo a entender melhor as concessões OIDC.
Imagine que está a viajar para diferentes países, e cada país exige um visto para a entrada. Neste cenário, o seu passaporte serve como a sua conta de utilizador, contendo as suas informações pessoais. Concessões OIDC são como os meios pelos quais você solicita um visto para entrar num país. Quando um visto é emitido para si, você obtém essencialmente o "token" para entrar nesse país.
Da mesma forma, ao usar uma aplicação, o pedido de concessão é a ação que você solicita ao servidor de autorização para lhe conceder acesso. O servidor de autorização valida a sua identidade, e emite-lhe o "visto" (token de acesso) para iniciar sessão na aplicação.
Tipos de concessões OIDC mais usados:
- Autorização de Concessão de Código: Este é o tipo de concessão mais comumente usado no OIDC. Envolve redirecionar o utilizador para um servidor de autorização, obter um código de autorização, redirecionar de volta para a aplicação e trocar o código por um token de acesso. Pense nisso como o processo padrão de solicitar um visto da embaixada antes de entrar num país estrangeiro.
- Concessão de Token de Atualização: No OIDC, este tipo de concessão permite que uma aplicação cliente obtenha um novo token de acesso usando um token de atualização que foi previamente emitido. É comumente usado para estender a sessão de um utilizador sem requerer que insiram suas credenciais novamente. Imagine que seu visto vem com um cartão mágico que permite prolongar a sua estadia no país estrangeiro sem passar novamente pelo controlo alfandegário.
- Concessão Implícita: Este tipo de concessão é usado para aplicações baseadas em navegador antigo e é menos seguro do que a Concessão de Código de Autorização. Ele devolve o token de acesso diretamente à aplicação cliente. Funciona como um "visto à chegada", pois nenhum pedido de visto prévio é necessário.
- Concessão de Credenciais de Cliente: Adequado para comunicação servidor a servidor, este tipo de concessão permite que uma aplicação cliente autentique diretamente com o servidor de autorização usando suas credenciais (ID de cliente e segredo de cliente). É como se um agente especial mostrasse uma insígnia de trabalho especial para entrar no país sem passar pelo processo de pedido de visto.
Modelo de objeto de concessão:
No Logto, a concessão é persistida no banco de dados como uma entidade de objeto, contendo informações como ID de conta de utilizador, ID de aplicação, recursos OIDC associados e âmbitos, tempo de expiração, e mais. Cada token de atualização e token de acesso está associado a um objeto de concessão específico.
Requisições de concessão:
Pedidos HTTP feitos ao servidor de autorização através de APIs. Uma aplicação cliente pode enviar requisições de concessão para o endpoint de token OIDC para vários propósitos, incluindo pedir uma nova concessão (por exemplo, iniciar sessão e obter tokens de atualização e acesso), atualizar detalhes de concessão (por exemplo, trocar um token de atualização por um novo token de acesso), ou revogar uma concessão (por exemplo, revogar todos os tokens emitidos para utilizadores com sessão iniciada e terminar o seu acesso).
Uma requisição de concessão de código de autorização típica é a seguinte:
Entendendo o erro "invalid_grant"
Encontrar um erro invalid_grant
no OIDC indica normalmente que o tipo de concessão ou os dados associados à requisição de concessão são inválidos ou não suportados. Aqui estão algumas razões comuns por detrás deste erro:
- Tipo de concessão incorreto: Usar o tipo de concessão errado para a sua aplicação pode resultar num erro
invalid_grant
. Certifique-se de que está a usar o tipo de concessão apropriado usando os SDKs Logto. - Redirecionar URIs incompatíveis: Ao trocar um código de autorização por tokens, o URI de redirecionamento usado na requisição deve coincidir com aquele usado durante a requisição de autorização inicial. Uma discordância pode resultar num erro
invalid_grant
. - Código de autorização expirado ou consumido: No fluxo de início de sessão do Código de Autorização, o código de autorização tem um tempo de vida limitado, e será marcado como "consumido" assim que for usado para adquirir tokens. Tentar trocar um código expirado ou consumido por um token de acesso resultará num erro
invalid_grant
. - Token de atualização expirado ou rodado: Ao trocar um token de atualização por um token de acesso, o erro
invalid_grant
ocorre se o token de atualização já expirou. Além disso, para maior segurança, o Logto permite rotação do token de atualização por predefinição. Solicitar ao endpoint do token com o mesmo token de atualização uma segunda vez é considerado usar um "token rotativo" e será rejeitado. - Dados obrigatórios ou cabeçalhos de requisição em falta: Ao compor uma requisição de concessão, os parâmetros obrigatórios e os cabeçalhos de requisição devem ser fornecidos para o determinado tipo de concessão. Por exemplo, o ID do cliente deve ser fornecido em todas as requisições de concessão, e o ID do cliente e o segredo do cliente devem ser fornecidos para a Concessão de Credenciais do Cliente. Este risco também pode ser mitigado usando os SDKs Logto.
- Outras razões: Este erro também pode ocorrer devido a razões como incompatibilidade de credenciais de cliente, concessão expirada ou não encontrada, token de atualização não encontrado, etc.
Resolução de problemas
Algumas dicas para resolver eficazmente o erro "invalid_grant":
- Sempre use um SDK cliente Logto para integrar o Logto na sua aplicação, para garantir que as requisições de concessão são feitas ao endpoint respetivo e com dados corretos.
- Verifique se suas credenciais de aplicação e URIs de redirecionamento correspondem às configurações no Admin Console.
- Evite fazer requisições redundantes, principalmente para SPAs como React e Vue, onde os componentes de página podem ser re-renderizados devido a mudanças de dependência. Certifique-se de que as funções usadas para trocar códigos ou tokens de atualização por tokens de acesso não estão sendo acionadas várias vezes com os mesmos parâmetros de requisição. Esse erro comum é cometido por alguns de nossos utilizadores. Normalmente, se você consegue ver várias requisições "token" no seu console de depuração, a primeira é bem-sucedida, mas as subsequentes todas falharam, verifique os parâmetros de suas requisições para ver se eles estão usando o mesmo "código" ou "token de atualização". Lembre-se, você só pode usar um código e token de atualização UMA VEZ em requisições de concessão.
- Reverifique os tempos de expiração. Por exemplo, se o seu token de atualização está expirado (por predefinição 14 dias) e você recebe o erro
invalid_grant
, deverá lidar com isso de forma apropriada iniciando novamente um fluxo de início de sessão de utilizador. Se você está a usar SDK Logto, você pode chamar a funçãosignIn()
novamente para redirecionar os seus utilizadores de volta para a página de início de sessão. - Monitorize os registos de auditoria. Vá para Admin Console → Audit Logs, encontre o registo de erro associado ao incidente e verifique o erro detalhado de stack trace. Normalmente, há uma razão mais específica na stack trace por detrás do erro
invalid_grant
, como "Concessão não encontrada" ou "Token de atualização expirado".
Notas Finais
O erro invalid_grant
pode ser desafiante e confuso para os iniciantes, mas com uma compreensão clara das concessões OIDC e atenção aos detalhes, você pode identificar e resolver o problema por si mesmo. Junte-se às nossas discussões no Discord ou GitHub, e deixe-nos saber se este blog ajudou a esclarecer a confusão e a identificar os problemas com que está deparando. A equipa de desenvolvimento do Logto está sempre pronta para lhe auxiliar.
Juntos, vamos construir uma experiência de autenticação sem problemas e segura para as suas apreciadas aplicações.