Quelle est l'intention du délai d'expiration du jeton d'identification dans OpenID Connect?

92

Dans OpenID Connect, un jeton d'accès a une heure d'expiration. Pour le flux de code d'autorisation, cela est généralement court (par exemple, 20 minutes), après quoi vous utilisez le jeton d'actualisation pour demander un nouveau jeton d'accès.

Le jeton d'identification a également une heure d'expiration. Ma question est quelle est l'intention de cela?

Tout délai d'expiration du jeton d'ID inférieur à l'heure d'expiration du jeton d'actualisation signifie que vous aurez éventuellement un jeton d'ID expiré, mais un jeton d'accès valide.

Alors êtes-vous censé:

  • donner à votre jeton d'identité une expiration plus longue que l'expiration du jeton d'actualisation, ou
  • définissez-le sur la même expiration que le jeton d'accès et prenez des mesures (quoi?) lorsqu'il expire, ou
  • consommer simplement le jeton d'identification dans votre client à la réception, puis ignorer le délai d'expiration après cela?

La spécification OpenID Connect indique simplement que lors de la validation d'un jeton d'identification,

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

qui (éventuellement) prend en charge la troisième option ci-dessus.


ÉDITER

Comme OpenID Connect s'appuie sur OAuth2, la réponse à la question supplémentaire ci-dessous se trouve dans la spécification OAuth2 qui dit:

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

Une question connexe est lorsque vous échangez un code d'autorisation pour les jetons, la même spécification indique que vous pourriez obtenir une réponse telle que:

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

Mais à quoi se rapporte "expires_in" dans ce cas? Le jeton d'accès, le jeton d'actualisation ou le jeton d'identification?

(Pour plus d'informations, IdentityServer3 définit cela sur l'heure d'expiration du jeton d'accès).

Appetere
la source

Réponses:

90

Je réponds à ma propre question car j'ai découvert que certaines des hypothèses derrière ma question étaient fausses, donc plus faciles à clarifier ici, plutôt que de réécrire la question.

Un jeton d'identification est destiné à prouver à un client que l'utilisateur s'est authentifié et qui il est en conséquence.

Lorsqu'un client reçoit un jeton d'identification, il fera généralement quelque chose comme le convertir en une ClaimsIdentity, et le conservera, par exemple en utilisant un cookie.

Le jeton d'identification doit être non expiré à ce stade d'utilisation (ce qu'il devrait être, car il vient d'être émis). Mais après cela, il n'est plus utilisé, donc peu importe s'il expire alors que l'utilisateur a toujours une session active. Le client dispose des informations d'authentification dont il a besoin et peut à son tour choisir sa propre politique pour la durée de la session avant que l'utilisateur ne doive se reconnecter.

Ma fausse hypothèse en posant la question était qu'un jeton d'identification et un jeton d'accès devaient être utilisés ensemble, et donc tous deux devaient avoir des dates d'expiration valides. Ceci est faux pour diverses raisons:

  • Les jetons d'identification sont uniquement destinés à l'authentification auprès d'un client (comme décrit ci-dessus).
  • Les jetons d'accès n'ont rien à voir avec les clients. Ils servent à accéder aux ressources et un client ne les gère que s'il a besoin à son tour d'appeler une ressource.
  • Quelque chose comme une application MVC ou WebForms autonome n'a besoin que d'un jeton d'identification. S'il n'appelle pas de ressource externe, il n'y a rien à quoi accorder l'accès, donc pas de jeton d'accès.
Appetere
la source
3
Avez-vous des références à ce sujet? Eugenio affirme que vous pouvez actualiser un jeton d'identification dans sa réponse. Est-ce vrai?
AndyD
6
Vous ne pouvez pas actualiser un jeton d'ID, dans le sens de prolonger son expiration (de la manière dont un jeton d'accès peut être actualisé à l'aide d'un jeton d'accès hors connexion). Mais si vous avez une session d'authentification non expirée avec le fournisseur OpenID Connect (par exemple un cookie après la connexion à IdentityServer3), lorsque vous répétez une demande de connexion, le fournisseur peut ignorer l'authentification (car les cookies indiquent que vous l'avez fait) et renvoyer simplement un nouveau jeton d'identification (et jeton d'accès si demandé). Cela ne fonctionne que si le cookie a une durée de vie plus longue que le jeton d'identification, bien sûr.
Appetere
1
Bien que vous puissiez le faire, je ne suis pas sûr qu'il soit correct de le faire. Cela ne serait pas non plus transparent pour l'utilisateur final, car cela nécessiterait une poignée de redirections de navigateur.
Kir
@Kir Si vous utilisez une application JavaScript à page unique (SPA), la première tentative de renouvellement du jeton d'accès serait généralement un processus en arrière-plan, de sorte que l'utilisateur final ne serait pas interrompu. Par exemple, si l'API de votre ressource répond que le jeton d'accès a expiré, le SPA envoie une demande en arrière-plan au serveur d'identité pour un nouveau jeton d'accès. Ce n'est qu'en cas d'échec (car le jeton d'identification a expiré) que vous devez demander à l'utilisateur de se reconnecter. Consultez l'exemple JavascriptImplicitClient sur github.com/IdentityServer/IdentityServer3.Samples/tree/master/... pour un exemple de code.
Appetere
Vous pouvez actualiser Id_token, si la prise en charge du fournisseur OIdC le renvoie à partir de la demande Refresh_token. Voir stackoverflow.com/questions/41168304/… et stackoverflow.com/questions/41741982/…
Michael Freidgeim
36

J'ai dû creuser cela pour mes propres raisons et l'écrire, alors je posterai ce que j'ai appris ici ...

Tout d'abord, je répondrai à la question au risque de déclarer l'évidence: le jeton d'identification ne peut pas être approuvé et son contenu doit être ignoré si l'heure actuelle est supérieure à l'heure expirée. La réponse de l'interrogateur indique qu'après l'authentification initiale de l'utilisateur, le jeton d'identification n'est plus utilisé. Cependant, comme le jeton d'identification est signé par le fournisseur d'identité, il pourrait certainement être utile à tout moment de donner un moyen de déterminer de manière fiable qui est l'utilisateur à d'autres services qu'une application pourrait utiliser. L'utilisation d'un simple identifiant d'utilisateur ou d'une adresse e-mail n'est pas fiable car il peut être facilement usurpé (n'importe qui peut envoyer une adresse e-mail ou un identifiant d'utilisateur), mais comme un jeton d'identification OIDC est signé par le serveur d'autorisation (qui a également généralement l'avantage d'être un tiers), il ne peut pas être usurpé et est un mécanisme d'authentification beaucoup plus fiable.

Par exemple, une application mobile peut vouloir être en mesure d'indiquer à un service backend qui est l'utilisateur qui utilise l'application et il peut avoir besoin de le faire après la brève période suivant l'authentification initiale, moment auquel le jeton d'identification est expiré, et donc, ne peut pas être utilisé pour authentifier l'utilisateur de manière fiable.

Par conséquent, tout comme le jeton d'accès (utilisé pour l'autorisation - spécifiant les autorisations dont dispose l'utilisateur) peut être actualisé, pouvez-vous actualiser le jeton d'identification (utilisé pour l'authentification - en spécifiant qui est l'utilisateur)? Selon la spécification OIDC, la réponse n'est pas évidente. Dans OIDC / OAuth, il y a trois "flux" pour obtenir des jetons, le flux de code d'autorisation, le flux implicite et le flux hybride (que je sauterai ci-dessous car c'est une variante des deux autres).

Pour le flux implicite dans OIDC / OAuth, vous demandez le jeton d'identification au point de terminaison d'autorisation en redirigeant l'utilisateur dans le navigateur vers le point de terminaison d'autorisation et en l'incluant id_tokencomme valeur du response_typeparamètre de demande. Une réponse d'authentification réussie de flux implicite est REQUISE pour inclure le id_token.

Pour le flux de code d'authentification , le client spécifie codecomme valeur du response_typeparamètre de demande lors de la redirection de l'utilisateur vers le point de terminaison d'autorisation. Une réponse réussie comprend un code d'autorisation. Le client client fait une demande au point d'extrémité de jeton avec le code d'autorisation et, conformément à la section 3.1.3.3 du cœur d'OIDC, la réponse DOIT inclure un jeton d'identification .

Donc, pour l'un ou l'autre flux, c'est ainsi que vous obtenez initialement le jeton d'identification, mais comment l'actualiser? La section 12 de l'OIDC: Utilisation de jetons d'actualisation contient l'instruction suivante concernant la réponse du jeton d'actualisation:

Lors de la validation réussie du jeton d'actualisation, le corps de la réponse est la réponse de jeton de la section 3.1.3.3 sauf qu'il peut ne pas contenir un id_token .

Il peut ne pas contenir de jeton d'ID et comme il n'y a aucun moyen spécifié de le forcer à inclure le jeton d'ID, vous devez supposer que la réponse ne contiendra pas le jeton d'ID. Donc, techniquement, il n'y a pas de manière spécifiée pour «actualiser» un jeton d'identification à l'aide d'un jeton d'actualisation. Par conséquent, le seul moyen d'obtenir un nouveau jeton d'identification est de ré-autoriser / authentifier l'utilisateur en redirigeant l'utilisateur vers le point de terminaison d'autorisation et en démarrant le flux implicite ou le flux de code d'authentification comme décrit ci-dessus. La spécification OIDC ajoute un promptparamètre de demande à la demande d'autorisation afin que le client puisse demander que le serveur d'autorisation n'invite pas l'utilisateur avec une interface utilisateur, mais la redirection doit toujours se produire.

Scott Willeke
la source
Si vous écrivez un logiciel général pour fonctionner avec un fournisseur d'autorisation arbitraire, vous ne pouvez pas compter sur le retour de id_token à partir de l'actualisation. Cependant, si vous travaillez avec le fournisseur particulier (tel que IdentityServer4), vous pouvez vérifier sa capacité et utiliser id_token reçu après la demande de rafraîchissement
Michael Freidgeim
Alors, comment le id_token peut-il être actualisé?
jwilleke
@jwilleke AFAIK, comme indiqué ci-dessus "la seule façon d'obtenir un nouveau jeton d'identification est de ré-autoriser / authentifier l'utilisateur en redirigeant l'utilisateur vers le point de terminaison d'autorisation"
Scott Willeke
@MichaelFreidgeim Intéressant, voulez-vous dire via le mécanisme Open ID Connect Discovery ? Comment faisons-nous cela exactement?
Scott Willeke
1
Une bonne réponse sur le "corps de réponse d'actualisation peut ne pas contenir un id_token". J'ai voté pour. En passant, je crois comprendre que les spécifications OIDC laissent une marge de manœuvre pour utiliser Refresh Token pour obtenir un nouveau jeton ID: le client peut le faire en spécifiant "id_token" comme l'un des champs d'application; mais la prudence générale s'applique toujours ici, car c'est le serveur d'authentification qui doit prendre la décision finale d'honorer la portée demandée.
RayLuo il y a
7

Si je comprends bien, conformément à cela et à la spécification OpenID Connect Core 1.0 , le jeton d'identification lui-même peut être stocké dans des cookies en tant que mécanisme pour conserver les sessions, et envoyé avec chaque demande nécessitant une authentification au client. Le client peut ensuite vérifier le jeton d'identification localement ou via le point de terminaison du vérificateur du fournisseur (s'il est fourni, comme le fait Google ). Si le jeton a expiré, il doit effectuer une autre demande d'authentification, sauf cette fois avec prompt=nonele paramètre URL. Assurez-vous également d'envoyer le jeton d'ID expiré dans le id_token_hintparamètre, sinon le fournisseur peut renvoyer une erreur.

Donc, il semble naturel que le jeton d'identification expire, mais prompt=nonegarantit que le nouveau jeton d'identification peut être obtenu en douceur sans intervention de l'utilisateur (à moins bien sûr que l'utilisateur ne soit déconnecté de cet OpenID).

Morrowless
la source
6

C'est la même intention: vous ne pouvez pas utiliser le id_tokenaprès son expiration. La principale différence est que an id_tokenest une structure de données et que vous n'aurez pas besoin d'appeler de serveurs ou de points de terminaison, car les informations sont codées dans le jeton lui-même. Un régulier access_tokenest généralement un artefact opaque (comme un GUID).

Le consommateur du id_tokendoit toujours vérifier la validité (temporelle) de celui-ci.

Je ne connais pas à 100% le SI, mais je suppose que c'est un domaine de commodité. Vous devriez toujours vérifier la expréclamation.

L'expiration n'est qu'une des validations. id_tokenLes s sont également signés numériquement et c'est aussi une validation que vous devez effectuer.

Eugenio Pace
la source
Merci Eugenio. La principale question que je me pose est ce que vous devez faire lorsque le jeton d'identification expire? J'ai pensé (peut-être à tort) que pour renouveler un jeton d'accès de courte durée, vous DEVEZ utiliser un jeton d'actualisation. Mais si le jeton d'identification a la même expiration que le jeton d'accès, vous aurez immédiatement un jeton d'identification expiré, il semblerait donc inutile de rafraîchir le jeton d'accès. Je pense qu'il me manque peut-être quelque chose ici!
Appetere
1
Vous utiliseriez le refresh_token (non révoqué) pour obtenir un nouveau access_token ou id_token. Ou simplement en tant qu'utilisateur de se connecter à nouveau. id_tokens sont logiquement équivalents à access_tokens. Juste un format différent.
Eugenio Pace
2
Ma dernière compréhension est que lorsque l'utilisateur a une session authentifiée avec le serveur d'autorisation, lorsque le jeton d'accès expire, la redirection 401 => 302 vers le serveur d'autorisation obtiendra de nouveaux jetons d'accès et d'identification sans intervention de l'utilisateur. Mais en mode hors ligne, un refresh_token ne retournera qu'un nouveau access_token qui indique qu'un utilisateur particulier est autorisé à accéder à certaines ressources. Il ne peut pas retourner un id_token, car cela signifierait que l'utilisateur particulier est authentifié et en mode hors ligne, ce qui n'est pas le cas.
Appetere
Ce serait une excellente réponse à une question concernant la différence entre id_token et access_token (en particulier lors de l'utilisation de jetons opaques / de référence). Concentrez-vous d'abord sur la réponse à la question, puis clarifiez comment les jetons d'accès et les jetons d'identification sont utilisés?
Trent
5

Actualiser un jeton signifie que vous pouvez l'utiliser à nouveau pour demander quelque chose au serveur d'autorisation (dans ce cas l'OP - le fournisseur OpenID-Connect) MÊME LORSQUE L'UTILISATEUR N'EST PAS CONNECTÉ. Vous ne l'autorisez généralement que pour des ressources limitées, et uniquement après que l'utilisateur s'est connecté et a été authentifié au moins une fois. Les jetons d'actualisation eux-mêmes doivent également être limités dans le temps.

Dans le flux implicite OIDC, vous appelez le point de terminaison d'autorisation
et recevez le jeton d'ID dans la réponse avec toutes les étendues et dans celles-ci toutes les informations sur les revendications.
Les appels ultérieurs à une API sont censés être effectués avec un flux de code .
Le flux implicite est destiné à activer une application javascript ou navigateur uniquement. Pas une application qui interagit avec un serveur.
Donc, même s'il y avait un moyen de «rafraîchir» ce jeton, vous ne devriez pas - du point de vue de la sécurité - lui permettre de vivre trop longtemps. Il sera volé et réutilisé par des utilisateurs non autorisés se faisant passer pour l'identifiant. Vous devez forcer une nouvelle connexion pour cela.

Dans le flux de code, vous appelez le point de terminaison d'autorisation de l'OP et recevez un code d'autorisation (également appelé jeton d'autorisation, ou authcode en abrégé). Cela devrait expirer de la même manière que le jeton id_token que vous avez reçu dans un flux implicite, pour les mêmes raisons et ne peut et ne doit pas être renouvelé.

Votre interface utilisateur ou application appelle ensuite le point de terminaison Token de l'OP et reçoit (parfois après le consentement supplémentaire de l'utilisateur via une interface utilisateur pour permettre l'utilisation de ses ressources possédées sur le serveur de l'OP) à la fois:

  • Un id_token, pour l'authentification - qui ne devrait plus jamais être utilisé dans les appels au serveur, sauf comme indice lors de la déconnexion, lorsque son expiration n'est plus importante, et donc, pour les raisons ci-dessus, doit être laissé expirer et ne jamais être actualisé.
  • Un access_token - qui plus tard, lors de l'appel d'une API, peut être donné au point de terminaison UserInfo de l'OP. Cela renverra les revendications, et l'API peut autoriser en conséquence.

Vous pouvez actualiser ce access_token, car il indique uniquement à l'API les revendications de l'utilisateur et les ressources (par étendues et par revendications de portée) que l'utilisateur a accepté de vous donner. Comme expliqué ci-dessus, cela permet d'autoriser l'accès même après que l'utilisateur n'est plus connecté. Bien sûr, vous ne souhaitez jamais autoriser l'actualisation de id_token, car vous ne souhaitez pas autoriser l'emprunt d'identité sans vous connecter.

pashute
la source
2
Ce que vous avez dit à propos du flux implicite est en partie incorrect. Un client qui utilise le flux implicite peut obtenir un jeton d'accès en plus d'un jeton d'ID et peut utiliser ce jeton d'accès pour interagir avec un serveur.
Shaun Luttin
Il existe une pratique courante, à savoir que lorsque l'id_token expire, le client demande de nouveaux jetons au serveur, de sorte que l'utilisateur n'ait pas besoin d'autoriser à nouveau. Par exemple, voir damienbod.com/2017/06/02/…
Michael Freidgeim
4

Je voulais publier cette réponse sous forme de commentaire, mais comme je n'ai pas été très actif sur StackOverflow, je suppose que je la poste comme réponse alternative.

Vous utilisez également id_tokencomme le id_token_hintlorsque vous essayez de déconnecter l'utilisateur d'une session http://openid.net/specs/openid-connect-session-1_0.html . Honnêtement, je ne pense pas que ce soit vraiment important si le id_tokenest expiré à ce stade, car vous ne vous souciez que de déconnecter un utilisateur particulier.

disparu
la source
4

TLDR;

Validez le jeton d'identification avant de faire confiance à ce qu'il dit.

Plus de détails

Quelle est l'intention du délai d'expiration du jeton d'identification dans OpenID Connect?

L'intention est de permettre au client de valider le jeton ID, et le client doit valider le jeton ID avant les opérations qui utilisent les informations du jeton ID .

À partir de la spécification OpenID Implicit Flow :

Si l'une des procédures de validation définies dans ce document échoue, toute opération nécessitant les informations qui n'ont pas été validées correctement DOIT être abandonnée et les informations qui n'ont pas pu être validées NE DOIVENT PAS être utilisées.

Pour corroborer cela, la documentation OpenID Connect de Google dit ceci à propos de la validation du jeton d'identification:

Une chose qui rend les jetons d'identification utiles est le fait que vous pouvez les transmettre à différents composants de votre application. Ces composants peuvent utiliser un jeton d'ID comme mécanisme d'authentification léger authentifiant l'application et l'utilisateur. Mais avant de pouvoir utiliser les informations du jeton d'identification ou de vous y fier comme une affirmation que l'utilisateur s'est authentifié, vous devez le valider.

Ainsi, si notre application cliente entreprend une action en fonction du contenu du jeton d'identification, nous devons à nouveau valider le jeton d'identification.

Shaun Luttin
la source