authentication - ¿Por qué hay un flujo de "código de autorización" en OAuth2 cuando el flujo "implícito" funciona tan bien?
oauth-2.0 (3)
Del párrafo 4.2 de la especificación de OAuth :
El tipo de concesión implícita se usa para obtener tokens de acceso (no admite la emisión de tokens de actualización) y está optimizado para clientes públicos que operan un URI de redirección particular. Estos clientes generalmente se implementan en un navegador usando un lenguaje de scripting como JavaScript.
Como un flujo basado en la redirección, el cliente debe ser capaz de interactuar con el agente de usuario del propietario del recurso (generalmente un navegador web) y capaz de recibir solicitudes entrantes (a través de la redirección) desde el servidor de autorizaciones.
A diferencia del tipo de concesión de código de autorización en el que el cliente realiza solicitudes separadas de token de autorización y acceso, el cliente recibe el token de acceso como resultado de la solicitud de autorización.
El tipo de concesión implícita no incluye la autenticación del cliente, y se basa en la presencia del propietario del recurso y el registro del URI de redirección. Como el token de acceso está codificado en el URI de redireccionamiento, puede estar expuesto al propietario del recurso y a otras aplicaciones que residen en el mismo dispositivo.
Entonces, ¿qué podemos considerar?
Esto es para OAuth público, es decir, cuando el cliente no necesita estar registrado y no tiene sus propios secretos del cliente. Pero, ¿qué servidor de autenticación comprueba la URL de redirección y esto es en realidad suficiente para la seguridad?
El token de acceso aparece en la barra de direcciones del navegador para que el usuario pueda copiar la url y enviarla a otra persona, y también se registra como usuario, es decir, algo así como la fijación de la sesión. Pero el navegador realiza una redirección adicional con el reemplazo del historial para eliminar el fragmento hash de la url. También es posible que un pirata informático robe el token de acceso olfateando un tráfico HTTP, pero esto se puede proteger fácilmente mediante HTTPS. Algunas extensiones de navegador maliciosas pueden tener acceso a las URL desde la barra de direcciones, pero esta es una situación mala como el certificado HTTPS roto. E incluso el flujo de código Auth no puede ayudar aquí éter. Entonces, lo que puedo ver es que pasar el token de acceso a través del fragmento hash de url es absolutamente seguro.
La separación del token de acceso efímero y token de actualización no sirve para nada cuando se usa un HTTPS y, para ser honesto, no es tan útil incluso en HTTP sin formato. Pero el hecho de que el cliente mediante flujo implícito no pueda recibir el token de actualización tampoco tiene sentido.
Por lo tanto, creo que deberíamos introducir un nuevo flujo de subvención "implícito seguro" que funciona estrictamente en https, permite actualizar el token (o debemos deshacernos de ellos en absoluto), y es preferible a Auth Cose grant flow
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 del "Código de autorización", el cliente (generalmente un servidor web) solo obtiene un código de autorización después de que el propietario del recurso (es decir, el usuario) le dio 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 simple.
La pregunta: ¿Por qué molestarse con el flujo del "Código de autorización" cuando el flujo "implícito" parece estar bien? ¿Por qué no usar también "Implícito" para un servidor web?
Es más trabajo tanto para el proveedor como para el cliente.
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 usar este flujo para las aplicaciones que necesitan acceso temporal (unas pocas horas) a los datos del usuario.
Devolver un token de acceso a los clientes de JavaScript también significa que su aplicación basada en el 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
tl; dr: Esto es todo por razones de seguridad.
OAuth 2.0 quería cumplir estos dos criterios:
- Desea permitir que los desarrolladores utilicen el URI de redirección no HTTPS porque no todos los desarrolladores tienen un servidor SSL habilitado y, si lo hacen, no siempre está configurado correctamente (certificados SSL de confianza no firmados, reloj sincronizado del servidor ...).
- No desea que los hackers puedan robar tokens de acceso / actualización mediante la interceptación de solicitudes.
Detalles abajo:
El flujo implícito solo es posible en un entorno de navegador debido a razones de seguridad:
En el flujo implícito, el token de acceso se pasa directamente como un fragmento hash (no como un parámetro URL). Una cosa importante sobre el fragmento hash es que, una vez que sigues un enlace que contiene un fragmento hash, solo el navegador conoce el fragmento hash. Los navegadores pasarán el fragmento hash directamente a la página web de destino (el URI de redirección / la página web del cliente). El fragmento hash tiene las siguientes propiedades:
- No son parte de la solicitud HTTP, por lo tanto, no pueden ser leídos por los servidores y, por lo tanto, no pueden ser interceptados por servidores / enrutadores intermediarios (esto es importante).
- Solo existen en el navegador, en el lado del cliente, por lo que la única forma de leer el fragmento hash es usar JavaScript que se ejecuta en la página.
Esto permite pasar un token de acceso directamente al cliente sin el riesgo de que sea interceptado por un servidor intermediario. Esto tiene la advertencia de que solo es posible el lado del cliente y necesita javascript ejecutando el lado del cliente para usar el token de acceso.
En el flujo de 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 de HTTP, por lo tanto, cualquier servidor intermediario / enrutador por el que pase su solicitud (podría ser cientos) podría lee el token de acceso si no estás utilizando una conexión encriptada (HTTPS) que permita lo que se conoce como ataques Man-in-the-middle.
Pasar el token de acceso directamente en un parámetro de URL podría ser posible en teoría, pero el servidor de autenticación debería asegurarse de que el URI de redirección utiliza 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 de que la solicitud HTTP esté completamente encriptada. Hacer que todos los desarrolladores compren un certificado SSL y configure SSL correctamente en su dominio sería un gran dolor y demoraría tremendamente la adopción. Esta es la razón por la cual se proporciona un "código de autorización" de uso único intermediario que solo el receptor legítimo podrá intercambiar (porque necesita el secreto del cliente) y que el código será inútil para posibles hackers que intercepten las solicitudes en transacciones no encriptadas (porque no conocen el secreto del cliente).
También podría argumentar que el flujo implícito es menos seguro, existen posibles vectores de ataque como falsificar el dominio al redirigir, por ejemplo, secuestrando la dirección IP del sitio web del cliente. Esta es una de las razones por las cuales el flujo implícito solo otorga tokens de acceso (que se supone que tienen un uso de tiempo limitado) y nunca actualizan los tokens (que son ilimitados en el tiempo). Para solucionar este problema, le aconsejo que aloje sus páginas web en un servidor habilitado para HTTPS siempre que sea posible.