¿Por qué hay un flujo de "Código de autorización" en OAuth2 cuando el flujo "implícito" funciona tan bien?
Con el flujo "implícito", el cliente (probablemente un navegador) obtendrá un token de acceso, después de que el propietario del recurso (es decir, el usuario) haya dado acceso.
Sin embargo, con el flujo de "Código de autorización", el cliente (normalmente un servidor web) sólo obtendrá un código de autorización después de que el propietario del recurso (es decir, el usuario) haya dado acceso. Con ese código de autorización, el cliente realiza otra llamada a la API pasando client_id y client_secret junto con el código de autorización para obtener el token de acceso. Todo bien descrito aquí .
Ambos flujos tienen exactamente el mismo resultado: un token de acceso. Sin embargo, el flujo "implícito" es mucho más sencillo.
La pregunta: ¿Por qué molestarse con el flujo de "Código de autorización", cuando el flujo "implícito" parece funcionar bien? ¿Por qué no utilizar "implícito" para el servidor web?
Es más trabajo tanto para el proveedor como para el cliente.
tl;dr: Todo esto se debe a razones de seguridad.
OAuth 2.0 quería cumplir estos dos criterios:
- Desea permitir que los desarrolladores utilicen URI de redireccionamiento no HTTPS porque no todos los desarrolladores tienen un servidor habilitado para SSL y, si lo tienen, no siempre está configurado correctamente (certificados SSL confiables y no autofirmados, reloj del servidor sincronizado...).
- No desea que los piratas informáticos puedan robar tokens de acceso/actualización interceptando solicitudes.
Detalles abajo:
El flujo implícito solo es posible en un entorno de navegador por razones de seguridad:
En el flujo implícito, el token de acceso se pasa directamente como un fragmento hash (no como un parámetro de URL). Una cosa importante sobre el fragmento de hash es que, una vez que sigues un enlace que contiene un fragmento de hash, sólo el navegador conoce el fragmento de hash. Los navegadores pasarán el fragmento hash directamente a la página web de destino (el URI de redireccionamiento/la página web del cliente). El fragmento hash tiene las siguientes propiedades:
- No son parte de la solicitud HTTP, por lo tanto, los servidores no pueden leerlos y, por lo tanto, no pueden ser interceptados por servidores/enrutadores intermediarios (esto es importante).
- Solo existen en el navegador (lado del cliente), por lo que la única forma de leer el fragmento hash es utilizando JavaScript que se ejecuta en la página.
Esto permite pasar un token de acceso directamente al cliente sin riesgo de que sea interceptado por un servidor intermediario. Esto tiene la advertencia de que solo es posible en el lado del cliente y necesita que JavaScript se ejecute en el lado del cliente para usar el token de acceso.
El flujo implícito también tiene problemas de seguridad que requieren más lógica para solucionar/evitar, por ejemplo:
- Un atacante podría obtener un token de acceso de un usuario en un sitio web/aplicación diferente (digamos si es el propietario del otro sitio web/aplicación), registrar el token en su sitio web y luego pasarlo como un parámetro de URL en su sitio web. por lo tanto, se hace pasar por el usuario en su sitio web. Para evitar esto, debe verificar el ID de cliente asociado con el token de acceso (por ejemplo, para Google puede usar el punto final tokeninfo) para asegurarse de que el token se emitió con su propio ID de cliente (es decir, mediante su propia aplicación) o verificar la firma. si está utilizando un IDToken (pero eso requiere su secreto de cliente).
- Si la solicitud de autenticación no se originó en su propia propiedad (llamados ataques de fijación de sesión), para evitar esto querrá generar un hash aleatorio desde su sitio web, guardarlo en una cookie y pasar ese mismo hash en el parámetro de URL de estado de la solicitud de autenticación, cuando el usuario regresa, verifica el parámetro de estado con la cookie y debe coincidir.
En el flujo del código de autorización no es posible pasar un token de acceso directamente en un parámetro de URL porque los parámetros de URL son parte de la solicitud HTTP, por lo tanto, cualquier servidor/enrutador intermediario por el cual pasaría su solicitud (podrían ser cientos) podría ser capaz de Lea el token de acceso si no está utilizando una conexión cifrada (HTTPS), lo que permite lo que se conoce como ataques Man-in-the-middle.
En teoría, pasar el token de acceso directamente en un parámetro de URL podría ser posible, pero el servidor de autenticación tendría que asegurarse de que el URI de redireccionamiento utilice HTTPS con cifrado TLS y un certificado SSL "confiable" (normalmente de una autoridad certificadora que no es gratuita). para asegurarse de que el servidor de destino sea legítimo y que la solicitud HTTP esté completamente cifrada. Hacer que todos los desarrolladores compren un certificado SSL y configuren SSL correctamente en su dominio sería una gran molestia y ralentizaría enormemente la adopción. Esta es la razón por la que se proporciona un "código de autorización" intermediario de un solo uso que sólo el receptor legítimo podrá intercambiar (porque necesita el secreto del cliente) y que el código será inútil para posibles piratas informáticos que intercepten las solicitudes a través de transacciones no cifradas. (porque no conocen el secreto del cliente).
También se podría argumentar que el flujo implícito es menos seguro y que existen posibles vectores de ataque, como la falsificación del dominio durante la redirección, por ejemplo, secuestrando la dirección IP del sitio web del cliente. Esta es una de las razones por las que el flujo implícito solo otorga tokens de acceso (que se supone que tienen un uso de tiempo limitado) y nunca actualiza tokens (que son ilimitados en el tiempo). Para solucionar este problema, le recomiendo que aloje sus páginas web en un servidor habilitado para HTTPS siempre que sea posible.
El flujo implícito hace que todo el flujo sea bastante fácil, pero también menos seguro .
Como la aplicación cliente, que normalmente es JavaScript que se ejecuta dentro de un navegador, es menos confiable, no se devuelven tokens de actualización para el acceso de larga duración.
Debe utilizar este flujo para aplicaciones que necesitan acceso temporal (unas horas) a los datos del usuario.
Devolver un token de acceso a los clientes JavaScript también significa que su aplicación basada en navegador debe tener especial cuidado; piense en los ataques XSS que podrían filtrar el token de acceso a otros sistemas.
https://labs.hybris.com/2012/06/05/oauth2-the-implicit-flow-aka-as-the-client-side-flow
Mi respuesta es: no se puede implementar el flujo implícito de forma segura y sencilla con el servidor de aplicaciones web.
El proceso de autorización de la aplicación web implica la interacción del usuario, por lo que el servidor de autenticación debe redirigir el navegador del usuario a la página de destino de la aplicación web después de la autenticación y el consentimiento del usuario (no veo otra forma de devolver al usuario a la aplicación web después de alguna interacción con Servidor de autenticación).
Entonces, el token debe pasarse a la aplicación web mediante una URL de redireccionamiento, ¿verdad?
Como explicó @NicolasGarnier en su respuesta y comentarios, no hay forma de pasar el token como un fragmento de URL; no llegará al servidor de la aplicación web.
Y pasar el token como parámetro de URL de la URL de redireccionamiento no sería seguro incluso bajo HTTPS: si la página de destino (sea "página de saludos") contiene recursos (imágenes, scripts, etc.), el navegador obtendrá estos recursos a través de la serie. de solicitudes HTTP(S) (cada una de las cuales tiene Referer
un encabezado HTTP que contiene la URL exacta de la "página de saludos", incluidos los parámetros de URL). Esta es la forma en que se puede filtrar el token.
Entonces parece que no hay forma de pasar el token en la URL de redireccionamiento. Es por eso que necesita una segunda llamada (ya sea desde el Servidor de autenticación al Cliente (pero ¿a qué URL?) o desde el Cliente al Servidor de autenticación (la segunda llamada en el flujo del Código de autorización))