¿Cuál es la intención del tiempo de vencimiento del token de identificación en OpenID Connect?

92

En OpenID Connect, un token de acceso tiene una fecha de caducidad. Para el flujo del código de autorización, esto suele ser breve (por ejemplo, 20 minutos), después de lo cual se usa el token de actualización para solicitar un nuevo token de acceso.

El token de ID también tiene una fecha de caducidad. Mi pregunta es ¿cuál es la intención de esto?

Cualquier tiempo de caducidad de token de ID menor que el tiempo de caducidad del token de actualización significará que eventualmente tendrá un token de ID caducado, pero un token de acceso válido.

Entonces, ¿estás destinado a:

  • otorgue a su token de ID una caducidad mayor que la caducidad del token de actualización, o
  • configúrelo con el mismo vencimiento que el token de acceso y realice alguna acción (¿qué?) cuando caduque, o
  • simplemente consuma el token de identificación en su cliente al recibirlo, luego ignore el tiempo de vencimiento después de eso.

La especificación de OpenID Connect solo dice que al validar un token de ID,

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

que (posiblemente) admite la tercera opción anterior.


EDITAR

Como OpenID Connect se basa en OAuth2, la respuesta a la pregunta complementaria a continuación se puede encontrar en la especificación de OAuth2 que dice:

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

Una pregunta relacionada es cuando intercambia un código de autorización por los tokens, la misma especificación dice que podría obtener una respuesta como:

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

Pero, ¿con qué se relaciona "expires_in" en este caso? ¿El token de acceso, el token de actualización o el token de identificación?

(Para obtener información, IdentityServer3 establece esto en el tiempo de vencimiento del token de acceso).

Appetere
fuente

Respuestas:

90

Estoy respondiendo mi propia pregunta porque descubrí que algunas de las suposiciones detrás de mi pregunta estaban equivocadas, por lo que es más fácil aclararlas aquí, en lugar de volver a escribir la pregunta.

Un token de ID está destinado a demostrarle a un Cliente que el usuario se ha autenticado y, como resultado, quiénes son.

Cuando un Cliente recibe un token de ID, generalmente hará algo como convertirlo en ClaimsIdentity y conservarlo, por ejemplo, usando una cookie.

El token de ID debe estar vencido en este punto de uso (que debería estarlo, ya que se acaba de emitir). Pero después de esto no se vuelve a utilizar, por lo que no importa si caduca mientras el usuario aún tiene una sesión activa. El Cliente tiene la información de autenticación que necesita y, a su vez, puede elegir su propia política de cuánto tiempo dura la sesión antes de que el usuario tenga que iniciar sesión nuevamente.

Mi suposición equivocada al hacer la pregunta fue que un token de identificación y un token de acceso deben usarse juntos y, por lo tanto, ambos deben tener fechas de caducidad válidas. Esto está mal por varias razones:

  • Los tokens de ID son solo para autenticarse en un Cliente (como se describe arriba).
  • Los tokens de acceso no tienen nada que ver con los Clientes. Son para acceder a los recursos y un Cliente solo los maneja si a su vez necesita llamar a un recurso.
  • Algo como una aplicación MVC o WebForms independiente solo necesita un token de ID. Si no está llamando a un recurso externo, no hay nada a lo que otorgar acceso, por lo que no hay token de acceso.
Appetere
fuente
3
¿Tiene alguna referencia para esto? Eugenio afirma que puede actualizar un token de identificación en su respuesta. ¿Es esto cierto?
AndyD
6
No puede actualizar un token de ID, en el sentido de extender su caducidad (de la misma manera que un token de acceso se puede actualizar usando un token de acceso sin conexión). Pero si tiene una sesión de autenticación no vencida con el proveedor de OpenID Connect (por ejemplo, una cookie después de iniciar sesión en IdentityServer3), cuando repita una solicitud de inicio de sesión, el proveedor puede omitir la autenticación (porque las cookies dicen que lo hizo) y simplemente devolver un nuevo token de identificación (y token de acceso si se solicita). Esto solo funciona si la cookie tiene una vida útil más larga que el token de identificación, por supuesto.
Apertura el
1
Si bien puede hacer esto, no estoy seguro de si es correcto hacerlo. Tampoco sería perfecto para el usuario final, ya que requeriría un puñado de redireccionamientos del navegador.
Kir
@Kir Si está utilizando una aplicación de una sola página de Javascript (SPA), el primer intento de renovación del token de acceso normalmente sería un proceso en segundo plano, por lo que el usuario final no sería interrumpido. Por ejemplo, si la API de su recurso responde que el token de acceso ha expirado, entonces el SPA realiza una solicitud en segundo plano al servidor de identidad para un nuevo token de acceso. Solo si esto falla (porque el token de ID ha caducado), debe pedirle al usuario que inicie sesión nuevamente. Consulte el ejemplo de JavascriptImplicitClient en github.com/IdentityServer/IdentityServer3.Samples/tree/master/… para obtener un código de ejemplo.
Apertura el
Puede actualizar Id_token, si el proveedor de OIdC lo devuelve de la solicitud Refresh_token. Ver stackoverflow.com/questions/41168304/… y stackoverflow.com/questions/41741982/…
Michael Freidgeim
36

Tuve que profundizar en esto por mis propias razones y lo escribí, así que publicaré lo que aprendí aquí ...

Primero, responderé la pregunta a riesgo de decir lo obvio: no se puede confiar en el token de ID y su contenido debe ignorarse si la hora actual es mayor que la hora vencida. La respuesta del interlocutor indica que después de la autenticación inicial del usuario, el token de identificación no se vuelve a utilizar. Sin embargo, dado que el ID Token está firmado por el proveedor de identidad, ciertamente podría ser útil en cualquier momento para brindar una forma de determinar de manera confiable quién es el usuario para otros servicios que una aplicación podría estar usando. Usar un ID de usuario o una dirección de correo electrónico simples no es confiable porque se puede falsificar fácilmente (cualquiera puede enviar una dirección de correo electrónico o ID de usuario), pero dado que el servidor de autorización firma un token de ID de OIDC (que también suele tener la ventaja de ser un tercero), no se puede falsificar y es un mecanismo de autenticación mucho más confiable.

Por ejemplo, es posible que una aplicación móvil desee poder decirle a un servicio de backend quién es el usuario que está utilizando la aplicación y es posible que deba hacerlo después del breve período posterior a la autenticación inicial, momento en el que caduca el token de identificación. y, por tanto, no se puede utilizar para autenticar de forma fiable al usuario.

Por lo tanto, al igual que el token de acceso (utilizado para la autorización, especificando qué permisos tiene el usuario) se puede actualizar, ¿ puede actualizar el token de ID (utilizado para la autenticación, especificando quién es el usuario)? Según la especificación OIDC, la respuesta no es obvia. En OIDC / OAuth hay tres "flujos" para obtener tokens, el flujo del código de autorización, el flujo implícito y el flujo híbrido (que omitiré a continuación porque es una variante de los otros dos).

Para el flujo implícito en OIDC / OAuth , solicita el token de identificación en el punto final de autorización redirigiendo al usuario en el navegador al punto final de autorización e incluyéndolo id_tokencomo el valor del response_typeparámetro de solicitud. Se REQUIERE una respuesta de autenticación exitosa de flujo implícito para incluir el id_token.

Para el flujo del Código de autenticación , el cliente especifica codecomo el valor del response_typeparámetro de solicitud al redirigir al usuario al punto final de autorización. Una respuesta exitosa incluye un código de autorización. El cliente realiza una solicitud al punto final del token con el código de autorización y, de acuerdo con la Sección 3.1.3.3 de OIDC Core, Respuesta de token exitosa, la respuesta DEBE incluir un token de identificación .

Entonces, para cualquier flujo, así es como obtiene inicialmente el token de identificación, pero ¿cómo lo actualiza? La Sección 12 de OIDC: El uso de tokens de actualización tiene la siguiente declaración sobre la respuesta de token de actualización:

Tras la validación exitosa del Refresh Token, el cuerpo de la respuesta es el Token Response de la Sección 3.1.3.3, excepto que puede que no contenga un id_token .

Es posible que no contenga un token de ID y, dado que no hay forma especificada para forzarlo a incluir el token de ID, debe asumir que la respuesta no contendrá el token de ID. Por lo tanto, técnicamente no hay una forma específica de "actualizar" un token de identificación utilizando un token de actualización. Por lo tanto, la única forma de obtener un nuevo Token de ID es volver a autorizar / autenticar al usuario redirigiéndolo al punto final de autorización e iniciando el flujo implícito o el flujo de código de autenticación como se describe anteriormente. La especificación OIDC agrega un promptparámetro de solicitud a la solicitud de autorización para que el cliente pueda solicitar que el servidor de autorización no solicite al usuario ninguna IU, pero la redirección aún tiene que ocurrir.

Scott Willeke
fuente
Si está escribiendo un software general para trabajar con un proveedor de autorización arbitrario, no puede confiar en devolver id_token desde la actualización. Sin embargo, si está trabajando con el proveedor en particular (como IdentityServer4), puede verificar su capacidad y usar id_token recibido después de la solicitud de actualización
Michael Freidgeim
Entonces, ¿cómo se puede actualizar el id_token?
jwilleke
@jwilleke AFAIK, como se dijo anteriormente, "la única forma de obtener un nuevo token de identificación es volver a autorizar / autenticar al usuario redirigiéndolo al punto final de autorización"
Scott Willeke
@MichaelFreidgeim Interesante, ¿te refieres al mecanismo de descubrimiento de Open ID Connect ? ¿Cómo lo hacemos exactamente?
Scott Willeke
1
Una buena respuesta sobre el "cuerpo de respuesta de actualización puede no contener un id_token". Voto a favor. Por cierto, tengo entendido que las especificaciones de OIDC dejan un margen de maniobra para utilizar Refresh Token para obtener un nuevo token de ID: el cliente puede hacerlo especificando "id_token" como uno de los alcances; pero la precaución general todavía se aplica aquí, porque es el servidor de autenticación el que toma la decisión final sobre si respetar el alcance solicitado.
RayLuo
7

Si lo entiendo correctamente, de acuerdo con esto y la especificación OpenID Connect Core 1.0 , el token de ID en sí puede almacenarse en cookies como un mecanismo para persistir las sesiones y enviarse con cada solicitud que requiera autenticación al Cliente. Luego, el Cliente puede verificar el token de ID localmente o mediante el punto final del verificador del Proveedor (si se proporciona, como lo hace Google ). Si el token está vencido, debe realizar otra solicitud de autenticación, excepto que esta vez prompt=noneen el parámetro de URL. También asegúrese de enviar el token de ID vencido en el id_token_hintparámetro; de lo contrario, el proveedor puede devolver un error.

Por lo tanto, parece natural que el token de ID caduque, pero prompt=nonegarantiza que el nuevo token de ID se pueda obtener sin problemas sin la intervención del usuario (a menos que, por supuesto, el usuario haya cerrado la sesión de ese OpenID).

Morrowless
fuente
6

Es la misma intención: no puede usar el id_tokendespués de que venza. La principal diferencia es que una id_tokenes una estructura de datos y no necesitará llamar a ningún servidor o punto final, ya que la información está codificada en el propio token. Un elemento regular access_tokensuele ser un artefacto opaco (como un GUID).

El consumidor del id_tokendebe verificar siempre la vigencia (temporal) del mismo.

No estoy 100% familiarizado con IS, pero supongo que es un campo de conveniencia. Siempre debe verificar el expreclamo.

La caducidad es solo una de las validaciones. id_tokenLos correos electrónicos también están firmados digitalmente y esa es también una validación que debe realizar.

Eugenio Pace
fuente
Gracias Eugenio. La pregunta principal que tengo es ¿qué debe hacer cuando caduca el token de identificación? Pensé (posiblemente erróneamente) que para renovar un token de acceso de corta duración TENÍA que usar un token de actualización. Pero si el token de ID tiene el mismo vencimiento que el token de acceso, inmediatamente tendrá un token de ID caducado, por lo que parecería inútil actualizar el token de acceso. ¡Creo que me estoy perdiendo algo aquí!
Apertura el
1
Usaría el refresh_token (no revocado) para obtener un nuevo access_token o id_token. O simplemente como usuario para iniciar sesión nuevamente. id_tokens son lógicamente equivalentes a access_tokens. Solo un formato diferente.
Eugenio Pace
2
Mi último entendimiento es que cuando el usuario tiene una sesión autenticada con el servidor de autorización, cuando el token de acceso expira, la redirección 401 => 302 al servidor de autorización obtendrá nuevos tokens de acceso e identificación sin la intervención del usuario. Pero en el modo fuera de línea, un refresh_token solo devolverá un nuevo access_token que dice que un usuario en particular puede acceder a algún recurso. No puede devolver un id_token, ya que eso estaría diciendo que el usuario en particular está autenticado y en modo fuera de línea, ese no es el caso.
Apertura el
Esta sería una gran respuesta a una pregunta sobre cuál es la diferencia entre id_token y access_token (especialmente cuando se usan tokens opacos / de referencia). Concéntrese en responder la pregunta primero y luego aclare cómo se usan los tokens de acceso y los tokens de identificación.
Trent
5

Actualizar un token significa que puede usarlo nuevamente para solicitar algo del servidor de autorización (en este caso, el OP, el proveedor de OpenID-Connect), INCLUSO CUANDO EL USUARIO NO HAYA INICIADO SESIÓN. Por lo general, permite esto solo para recursos limitados y solo después de que el usuario haya iniciado sesión y se haya autenticado al menos una vez. Los propios tokens de actualización también deben estar limitados en el tiempo.

En el flujo implícito de OIDC , usted llama al extremo de autorización
y recibe el token de ID en la respuesta junto con todos los ámbitos y en ellos toda la información de las reclamaciones.
Las llamadas posteriores a una API deben realizarse con flujo de código .
El flujo implícito está destinado a habilitar una aplicación solo javascript o solo navegador. No es una aplicación que interactúe con un servidor.
Por lo tanto, incluso si hubiera una forma de "actualizar" este token, no debería, en términos de seguridad, permitir que viva demasiado tiempo. Será robado y reutilizado por usuarios no autorizados que se hagan pasar por la identificación. Debería forzar un nuevo inicio de sesión para eso.

En el flujo de código , llama al extremo de autorización del OP y recibe un código de autorización (también llamado token de autorización, o authcode para abreviar). Esto debería caducar de forma similar al id_token que recibió en el flujo implícito, por las mismas razones y no puede ni debe renovarse.

Su IU o aplicación luego llama al punto final Token del OP y recibe (a veces después del consentimiento adicional del usuario a través de una IU para permitir el uso de sus recursos propios en el servidor del OP) ambos:

  • Un id_token, para autenticación, que nunca debe usarse nuevamente en llamadas al servidor, excepto como una pista durante el cierre de sesión, cuando su vencimiento ya no es importante y, por lo tanto, por las razones anteriores, debe dejarse que caduque y nunca actualizarse.
  • Un access_token, que más adelante, al llamar a una API, se puede proporcionar al punto final UserInfo del OP. Eso devolverá las reclamaciones y la API puede autorizar en consecuencia.

Puede actualizar este access_token, ya que solo le dice a la API qué reclamos tiene el usuario y qué recursos (por alcances y reclamos de cada alcance) el usuario acordó darle. Como se explicó anteriormente, esto es para permitir el acceso incluso después de que el usuario ya no haya iniciado sesión. Por supuesto, nunca desea permitir que se actualice id_token, porque no desea permitir la suplantación de identidad sin iniciar sesión.

pashute
fuente
2
Lo que ha dicho sobre el flujo implícito es parcialmente incorrecto. Un cliente que usa el flujo implícito puede obtener un token de acceso además de un token de ID y puede usar ese token de acceso para interactuar con un servidor.
Shaun Luttin
Existe una práctica común, que cuando el id_token expira, el cliente solicita nuevos tokens del servidor, de modo que el usuario no necesita autorizar nuevamente. Por ejemplo, ver damienbod.com/2017/06/02/…
Michael Freidgeim
4

Quería publicar esta respuesta como comentario, pero como no he estado muy activo en StackOverflow, supongo que lo estoy publicando como una respuesta alternativa.

También puede utilizar id_tokencomo id_token_hintcuando se intenta conectar al usuario salir de una sesión de http://openid.net/specs/openid-connect-session-1_0.html . Honestamente, no creo que realmente importe si id_tokenha caducado en este momento, ya que solo le preocupa cerrar la sesión de un usuario en particular.

dgonee
fuente
4

TLDR;

Valide el token de ID antes de confiar en lo que dice.

Más detalles

¿Cuál es la intención del tiempo de vencimiento del token de ID en OpenID Connect?

La intención es permitir que el cliente valide el token de ID, y el cliente debe validar el token de ID antes de las operaciones que utilizan la información del token de ID .

De la especificación de flujo implícito de OpenID :

Si alguno de los procedimientos de validación definidos en este documento falla, cualquier operación que requiera la información que no pudo validar correctamente DEBE ser abortada y la información que no pudo validar NO DEBE usarse.

Para corroborar eso, la documentación de OpenID Connect de Google dice esto sobre la validación del token de identificación:

Una cosa que hace que los tokens de identificación sean útiles es el hecho de que puede pasarlos por diferentes componentes de su aplicación. Estos componentes pueden usar un token de identificación como un mecanismo de autenticación ligero que autentica la aplicación y el usuario. Pero antes de que pueda utilizar la información del token de ID o confiar en ella como una afirmación de que el usuario se ha autenticado, debe validarla.

Por lo tanto, si nuestra aplicación cliente va a realizar alguna acción en función del contenido del token de ID, debemos volver a validar el token de ID.

Shaun Luttin
fuente