Qual é a intenção do tempo de expiração do token de ID no OpenID Connect?

95

No OpenID Connect, um token de acesso tem um tempo de expiração. Para o fluxo do código de autorização, isso normalmente é curto (por exemplo, 20 minutos) após o qual você usa o token de atualização para solicitar um novo token de acesso.

O token de ID também tem um tempo de expiração. Minha pergunta é qual é a intenção disso?

Qualquer tempo de expiração do token de ID menor que o tempo de expiração do token de atualização significará que você eventualmente terá um token de ID expirado, mas um token de acesso válido.

Então você deve:

  • dar ao seu token de ID uma expiração mais longa do que a expiração do token de atualização, ou
  • configure-o com a mesma expiração do token de acesso e execute alguma ação (o quê?) quando ele expirar, ou
  • basta consumir o token de ID em seu cliente no recebimento e ignorar o tempo de expiração depois disso?

A especificação OpenID Connect apenas diz que, ao validar um token de ID,

"The current time MUST be before the time represented by the exp Claim."

que (possivelmente) suporta a terceira opção acima.


EDITAR

Como o OpenID Connect se baseia no OAuth2, a resposta à pergunta complementar abaixo pode ser encontrada na especificação OAuth2 que diz:

expires_in
     RECOMMENDED.  The lifetime in seconds of the access token.

Uma questão relacionada é quando você troca um código de autorização para os tokens, a mesma especificação diz que você pode obter uma resposta como:

{
 "access_token": "SlAV32hkKG",
 "token_type": "Bearer",
 "refresh_token": "8xLOxBtZp8",
 "expires_in": 3600,
 "id_token": "eyJhbG[...]"
}

Mas com o que "expires_in" se relaciona neste caso? O token de acesso, o token de atualização ou o token de ID?

(Para obter informações, IdentityServer3 define isso para o tempo de expiração do token de acesso).

Appetere
fonte

Respostas:

92

Estou respondendo à minha própria pergunta, pois descobri que algumas das suposições por trás da minha pergunta estavam erradas, então é mais fácil esclarecer aqui, em vez de reescrever a pergunta.

Um token de ID serve para provar a um cliente que o usuário foi autenticado e quem ele é como resultado.

Quando um cliente recebe um token de ID, ele geralmente faz algo como convertê-lo em ClaimIdentity e persistir nisso, por exemplo, usando um cookie.

O token de ID não pode expirar neste ponto de uso (o que deve ser, já que acaba de ser emitido). Mas depois disso não é usado novamente, então não importa se ele expira enquanto o usuário ainda tem uma sessão ativa. O cliente tem as informações de autenticação de que precisa e, por sua vez, pode escolher sua própria política para a duração da sessão antes que o usuário precise fazer o login novamente.

Minha suposição errada ao fazer a pergunta foi que um token de ID e um token de acesso devem ser usados ​​juntos e, portanto, ambos precisam ter datas de expiração válidas. Isso está errado por vários motivos:

  • Os tokens de ID são apenas para autenticação em um cliente (conforme descrito acima).
  • Os tokens de acesso não têm nada a ver com os clientes. Eles são para acesso a recursos e um Cliente só os trata se, por sua vez, precisar chamar um recurso.
  • Algo como um aplicativo MVC ou WebForms independente precisa de um token de ID. Se não estiver chamando um recurso externo, não há nada para conceder acesso, portanto, nenhum token de acesso.
Appetere
fonte
3
Você tem alguma referência para isso? Eugenio afirma que você pode atualizar um token de identificação em sua resposta. Isso é verdade?
AndyD
7
Você não pode atualizar um token de ID, no sentido de estender sua validade (da mesma forma que um token de acesso pode ser atualizado usando um token de acesso offline). Mas se você tiver uma sessão de autenticação não expirada com o provedor OpenID Connect (por exemplo, um cookie após fazer login no IdentityServer3), quando você repetir uma solicitação de login, o provedor pode pular a autenticação (porque os cookies dizem que você fez isso) e apenas retornar um novo token de ID (& token de acesso, se solicitado). Isso só funciona se o cookie tiver uma vida útil mais longa do que o token de ID, é claro.
Appetere
1
Embora você possa fazer isso, não tenho certeza se é correto fazê-lo. Também não seria fácil para o usuário final, pois exigiria vários redirecionamentos do navegador.
Kir de
@Kir Se você estiver usando um aplicativo Javascript de página única (SPA), a primeira tentativa de renovação do token de acesso normalmente será um processo em segundo plano, para que o usuário final não seja interrompido. Por exemplo, se a API do seu recurso responder que o token de acesso expirou, o SPA fará uma solicitação em segundo plano ao Identity Server para um novo token de acesso. Somente se isso falhar (porque o token de ID expirou) você deve pedir ao usuário para fazer o login novamente. Consulte a amostra JavascriptImplicitClient em github.com/IdentityServer/IdentityServer3.Samples/tree/master/… para obter o código de exemplo.
Appetere de
Você pode atualizar Id_token, se o suporte do provedor OIdC retorná-lo da solicitação Refresh_token. Consulte stackoverflow.com/questions/41168304/… e stackoverflow.com/questions/41741982/…
Michael Freidgeim
38

Eu tive que cavar nisso por meus próprios motivos e escrevi, então vou postar o que aprendi aqui ...

Em primeiro lugar, responderei à pergunta correndo o risco de afirmar o óbvio: o token de ID não é confiável e seu conteúdo deve ser ignorado se o tempo atual for maior que o tempo expirado. A resposta do questionador afirma que, após a autenticação inicial do usuário, o token de identificação não é usado novamente. No entanto, como o token de identificação é assinado pelo provedor de identidade, certamente pode ser útil a qualquer momento fornecer uma maneira confiável de determinar quem é o usuário para outros serviços que um aplicativo possa estar usando. Usar um simples ID de usuário ou endereço de e-mail não é confiável porque pode ser facilmente falsificado (qualquer pessoa pode enviar um endereço de e-mail ou ID de usuário), mas uma vez que um token de ID OIDC é assinado pelo servidor de autorização (que geralmente também tem a vantagem de ser um terceiro), não pode ser falsificado e é um mecanismo de autenticação muito mais confiável.

Por exemplo, um aplicativo móvel pode querer dizer a um serviço de back-end quem é o usuário que está usando o aplicativo e pode precisar fazer isso após o breve período após a autenticação inicial, momento em que o token de ID expira, e, portanto, não pode ser usado para autenticar o usuário de forma confiável.

Portanto, assim como o token de acesso (usado para autorização - especificando quais permissões o usuário tem) pode ser atualizado, você pode atualizar o token de ID (usado para autenticação - especificando quem é o usuário)? De acordo com a especificação OIDC, a resposta não é óbvia. No OIDC / OAuth, há três "fluxos" para obter tokens, o fluxo do Código de autorização, o fluxo Implícito e o fluxo Híbrido (que ignorarei abaixo porque é uma variante dos outros dois).

Para o fluxo implícito em OIDC / OAuth, você solicita o token de ID no terminal de autorização redirecionando o usuário no navegador para o terminal de autorização e incluindo id_tokeno valor do response_typeparâmetro de solicitação. Uma resposta de autenticação bem-sucedida de fluxo implícito é NECESSÁRIA para incluir o id_token.

Para o fluxo do Código de autenticação , o cliente especifica codecomo o valor do response_typeparâmetro de solicitação ao redirecionar o usuário para o terminal de autorização. Uma resposta bem-sucedida inclui um código de autorização. O cliente cliente faz uma solicitação ao terminal de token com o código de autorização e, de acordo com o OIDC Core Seção 3.1.3.3 Resposta de Token com Sucesso, a resposta DEVE incluir um Token de ID .

Portanto, para qualquer um dos fluxos, é assim que você obtém inicialmente o token de ID, mas como você o atualiza? A seção 12 do OIDC: Usando tokens de atualização contém a seguinte declaração sobre a resposta do token de atualização:

Após a validação bem-sucedida do token de atualização, o corpo da resposta é a resposta do token da Seção 3.1.3.3, exceto que pode não conter um id_token .

Ele pode não conter um token de ID e, como não há nenhuma maneira especificada de forçá-lo a incluir o token de ID, você deve presumir que a resposta não conterá o token de ID. Portanto, tecnicamente, não há uma maneira especificada de "atualizar" um token de ID usando um token de atualização. Portanto, a única maneira de obter um novo token de ID é reautorizar / autenticar o usuário redirecionando-o para o terminal de autorização e iniciando o fluxo implícito ou o fluxo de código de autenticação conforme descrito acima. A especificação OIDC adiciona um promptparâmetro de solicitação à solicitação de autorização para que o cliente possa solicitar que o servidor de autorização não solicite ao usuário nenhuma IU, mas o redirecionamento ainda precisa acontecer.

Scott Willeke
fonte
Se você está escrevendo um software geral para trabalhar com um provedor de autorização arbitrário, não pode contar com o retorno de id_token da atualização. No entanto, se você estiver trabalhando com o provedor específico (como IdentityServer4), pode verificar sua capacidade e usar id_token recebido após a solicitação de atualização
Michael Freidgeim
Então, como o id_token pode ser atualizado?
jwilleke
@jwilleke AFAIK, como dito acima "a única maneira de obter um novo token de ID é reautorizar / autenticar o usuário redirecionando o usuário para o endpoint de autorização"
Scott Willeke
@MichaelFreidgeim Interessante, você quer dizer por meio do mecanismo Open ID Connect Discovery ? Como exatamente fazemos isso?
Scott Willeke
1
Boa resposta sobre o "corpo de resposta da atualização pode não conter um id_token". Votado. A propósito, meu entendimento é que as especificações OIDC deixam uma margem de manobra para usar o token de atualização para obter um novo token de ID: o cliente pode fazer isso especificando "id_token" como um do escopo; mas o cuidado geral ainda se aplica aqui, porque é o servidor de autenticação que toma a decisão final sobre se honrará o escopo solicitado.
RayLuo de
7

Se bem entendi, de acordo com esta e as especificações do OpenID Connect Core 1.0 , o próprio token de ID pode ser armazenado em cookies como um mecanismo para persistir as sessões e enviado com cada solicitação de autenticação que exige ao Cliente. O cliente pode então verificar o token de ID localmente ou por meio do ponto de extremidade do verificador do provedor (se fornecido, como o Google faz ). Se o token estiver expirado, ele deve fazer outra solicitação de autenticação, mas desta vez com prompt=noneno parâmetro URL. Certifique-se também de enviar o token de ID expirado no id_token_hintparâmetro, caso contrário, o Provedor pode retornar um erro.

Portanto, parece natural que o token de ID expire, mas prompt=nonegarante que o novo token de ID possa ser obtido sem intervenção do usuário (a menos, é claro, que o usuário seja desconectado desse OpenID).

Morrowless
fonte
6

É a mesma intenção: você não pode usar o id_token depois que ele expirar. A principal diferença é que id_tokené uma estrutura de dados e você não precisa chamar nenhum servidor ou endpoint, pois a informação é codificada no próprio token. Um regular access_tokené geralmente um artefato opaco (como um GUID).

O consumidor do id_tokendeve sempre verificar a (tempo) validade do mesmo.

Não estou 100% familiarizado com IS, mas acho que é um campo de conveniência. Você deve sempre verificar a expreclamação.

A expiração é apenas uma das validações. id_tokens também são assinados digitalmente e essa também é uma validação que você deve executar.

Eugenio Pace
fonte
Obrigado Eugenio. A principal dúvida que tenho é o que você deve fazer quando o token de ID expirar. Pensei (possivelmente erroneamente) que, para renovar um token de acesso de curta duração, você TINHA que usar um token de atualização. Mas se o token de ID tiver a mesma expiração que o token de acesso, você terá imediatamente um token de ID expirado, então pareceria inútil atualizar o token de acesso. Acho que posso estar faltando alguma coisa aqui!
Appetere
1
Você usaria o (não revogado) refresh_token para obter um novo access_token ou id_token. Ou simplesmente como o usuário para fazer o login novamente. id_tokens são logicamente equivalentes a access_tokens. Apenas um formato diferente.
Eugenio Pace
2
Meu entendimento mais recente é que quando o usuário tem uma sessão autenticada com o servidor de autorização, quando o token de acesso expira, o redirecionamento 401 => 302 para o servidor de autorização obterá novos tokens de acesso e ID sem a intervenção do usuário. Mas no modo offline, um refresh_token retornará apenas um novo access_token que diz que um determinado usuário tem permissão para acessar algum recurso. Ele não pode retornar um id_token, pois isso significaria que o usuário específico está autenticado e em modo offline, não é o caso.
Appetere
Esta seria uma ótima resposta a uma pergunta sobre qual é a diferença entre id_token e access_token (especialmente ao usar tokens opacos / de referência). Concentre-se em responder à pergunta primeiro e, em seguida, esclarecer como os tokens de acesso e os tokens de id são usados?
Trent
5

Atualizar um token significa que você pode usá-lo novamente para solicitar algo do servidor de autorização (neste caso o OP - o provedor OpenID-Connect) MESMO QUANDO O USUÁRIO NÃO ESTIVER LOGADO. Normalmente, você permite isso apenas para recursos limitados e somente depois que o usuário fizer login e ser autenticado pelo menos uma vez. Os próprios tokens de atualização também devem ser limitados no tempo.

No fluxo implícito OIDC , você chama o endpoint de autorização
e recebe o token de ID na resposta junto com todos os escopos e neles todas as informações de declarações.
As chamadas subsequentes para uma API devem ser feitas com fluxo de código .
O fluxo implícito destina-se a habilitar um aplicativo somente javascript ou somente navegador Não é um aplicativo que está interagindo com um servidor.
Portanto, mesmo que haja uma maneira de "atualizar" esse token, você não deve - em termos de segurança - deixá-lo durar muito tempo. Ele será roubado e reutilizado por usuários não autorizados que se fazem passar pelo id. Você deve forçar um novo login para isso.

No fluxo de código, você chama o endpoint de autorização do OP e recebe um código de autorização (também chamado de token de autorização, ou authcode abreviadamente). Isso deve expirar de forma semelhante ao id_token que você recebeu no fluxo implícito, pelos mesmos motivos e não pode e não deve ser renovado.

Sua IU ou aplicativo, em seguida, chama o endpoint de Token do OP e recebe (às vezes após o consentimento do usuário por meio de uma IU para permitir o uso de seus recursos de propriedade no servidor do OP):

  • Um id_token, para autenticação - que nunca deve ser usado novamente em chamadas ao servidor, exceto como uma dica durante o logout, quando sua expiração não é mais importante, e assim, pelos motivos acima deve ser deixado expirar, e nunca ser atualizado.
  • Um access_token - que mais tarde, ao chamar uma API, pode ser fornecido ao terminal UserInfo do OP. Isso retornará as declarações e a API pode autorizar de acordo.

Você pode atualizar este access_token, uma vez que ele informa à API quais declarações o usuário possui e quais recursos (por escopos e as declarações de cada escopo) o usuário concordou em fornecer a você. Conforme explicado acima, isso é para permitir o acesso mesmo depois que o usuário não estiver mais logado. Claro que você nunca deseja permitir que o id_token seja atualizado, porque você não quer permitir a representação sem fazer login.

pashute
fonte
2
O que você disse sobre o fluxo implícito está parcialmente incorreto. Um cliente que usa o fluxo implícito pode obter um token de acesso além de um token de ID e pode usar esse token de acesso para interagir com um servidor.
Shaun Luttin
É uma prática comum que, quando o id_token expira, o cliente solicita novos tokens do servidor, para que o usuário não precise autorizar novamente. Por exemplo, consulte damienbod.com/2017/06/02/…
Michael Freidgeim
4

Eu queria postar esta resposta como um comentário, mas como não tenho sido muito ativo no StackOverflow, acho que estou postando como uma resposta alternativa.

Você também pode usar id_tokencomo id_token_hintao tentar desconectar o usuário de uma sessão http://openid.net/specs/openid-connect-session-1_0.html . Sinceramente, não acho que realmente importe se o id_tokentiver expirado neste ponto, já que você só está preocupado em desconectar um usuário específico.

dgonee
fonte
4

TLDR;

Valide o token de ID antes de confiar no que ele diz.

Mais detalhes

Qual é a intenção do tempo de expiração do token de ID no OpenID Connect?

A intenção é permitir que o cliente valide o token de ID, e o cliente deve validar o token de ID antes das operações que usam as informações do token de ID .

Nas especificações de fluxo implícito do OpenID :

Se algum dos procedimentos de validação definidos neste documento falhar, quaisquer operações que requeiram as informações que não foram validadas corretamente DEVEM ser abortadas e as informações que não foram validadas NÃO DEVEM ser utilizadas.

Para corroborar isso, a documentação do OpenID Connect do Google diz o seguinte sobre a validação do token de ID:

Uma coisa que torna os tokens de ID úteis é o fato de que você pode passá-los entre diferentes componentes do seu aplicativo. Esses componentes podem usar um token de ID como um mecanismo de autenticação leve, autenticando o aplicativo e o usuário. Mas antes de usar as informações no token de ID ou confiar nelas como uma afirmação de que o usuário foi autenticado, você deve validá-las.

Portanto, se nosso aplicativo cliente vai realizar alguma ação com base no conteúdo do token de ID, devemos validar novamente o token de ID.

Shaun Luttin
fonte