¿Cuál es el propósito del tipo de autorización de concesión implícita en OAuth 2?


254

No sé si solo tengo algún tipo de punto ciego o qué, pero he leído las especificaciones de OAuth 2 muchas veces y he leído los archivos de la lista de correo, y todavía no he encontrado una buena explicación de por qué la Subvención implícita Se ha desarrollado un flujo para obtener tokens de acceso. En comparación con la concesión del código de autorización, parece simplemente renunciar a la autenticación del cliente sin una razón muy convincente. ¿Cómo se "optimiza para clientes implementados en un navegador usando un lenguaje de script" (para citar la especificación)?

Ambos flujos comienzan igual (fuente: http://tools.ietf.org/html/draft-ietf-oauth-v2-22 ):

  1. El cliente inicia el flujo dirigiendo el agente de usuario del propietario del recurso al punto final de autorización.
  2. El servidor de autorización autentica al propietario del recurso (a través del agente de usuario) y establece si el propietario del recurso otorga o rechaza la solicitud de acceso del cliente.
  3. Asumiendo que el propietario del recurso concede acceso, el servidor de autorización redirige al agente de usuario nuevamente al cliente utilizando el URI de redireccionamiento proporcionado anteriormente (en la solicitud o durante el registro del cliente).
    • El URI de redireccionamiento incluye un código de autorización (flujo de código de autorización)
    • El URI de redireccionamiento incluye el token de acceso en el fragmento de URI (flujo implícito)

Aquí es donde se dividen los flujos. En ambos casos, el URI de redireccionamiento en este punto es a algún punto final alojado por el cliente:

  • En el flujo del código de autorización, cuando el agente de usuario alcanza ese punto final con el código de autorización en el URI, el código en ese punto final intercambia el código de autorización junto con sus credenciales de cliente por un token de acceso que luego puede usar según sea necesario. Podría, por ejemplo, escribirlo en una página web a la que pueda acceder un script en la página.
  • El flujo implícito omite este paso de autenticación del cliente por completo y solo carga una página web con el script del cliente. Aquí hay un lindo truco con el fragmento de URL que evita que el token de acceso se pase demasiado, pero el resultado final es esencialmente el mismo: el sitio alojado por el cliente sirve una página con algún script que puede tomar el token de acceso .

De ahí mi pregunta: ¿qué se ha ganado aquí omitiendo el paso de autenticación del cliente?



55
El enlace en el comentario anterior está muerto. Aquí hay uno actualizado
AndrewR

3
He leído todas las respuestas aquí, pero todavía no entiendo cómo no puede ser seguro no requerir un secreto de cliente privado para obtener un token de acceso. Digamos que TrustedAppDeveloper lanza TrustedPopularApp que permite a los usuarios otorgarle permisos (digamos usando Twitter oauth) usando una concesión implícita. Si soy EvilAppDeveloper, ¿qué me impide hacer una aplicación que pasa TrustedPopularAppId como client_id en una solicitud de concesión implícita, y luego realiza acciones (como enviar spam a un feed) en nombre del usuario, que ahora parece que provienen de TrustedPopularApp ?
adevine

Me pregunto lo mismo que una adevine. Pero, ¿las aplicaciones más probables que requieren una solicitud de subvención implícita no necesitan más autenticación, ya que todas se obtienen?
Mave

13
@adevine Lo que evitaría que EvilApp en su escenario se autentique en Twitter como TrustedPopularApp es que no podría recibir las devoluciones de llamadas de Twitter, siempre se enviarían al URI que se definió al registrar la identificación del cliente
Ivan

Respuestas:


196

Aquí están mis pensamientos:

El propósito del código de autenticación + token en el flujo del código de autorización es que el secreto del token y del cliente nunca se expondrá al propietario del recurso porque viajan de servidor a servidor.

Por otro lado, el flujo de concesión implícito es para clientes que se implementan completamente usando JavaScript y se ejecutan en el navegador del propietario del recurso. No necesita ningún código del lado del servidor para usar este flujo. Entonces, si todo sucede en el navegador del propietario del recurso, ya no tiene sentido emitir código de autenticación y secreto del cliente, porque el token y el secreto del cliente aún se compartirán con el propietario del recurso. La inclusión del código de autenticación y el secreto del cliente solo hace que el flujo sea más complejo sin agregar más seguridad real.

Entonces, la respuesta sobre "¿qué se ha ganado?" es "simplicidad".


44
Gracias. Es un buen punto que en el flujo del código de autorización, el propietario del recurso nunca necesita ver el token de acceso, mientras que en los clientes de JavaScript eso es inevitable. Sin embargo, el secreto del cliente aún se podía guardar de los clientes de JavaScript utilizando el flujo de código de autorización: después de autenticar y obtener un token de acceso, el código del lado del servidor pasaría el token al cliente de JavaScript. Sin embargo, lo que ahora veo es que el flujo de concesión implícito permite la distribución de SDK de JavaScript oauth, como el de Facebook, liberando a los desarrolladores de tener que escribir su propio código oauth por completo.
Dan Taflin

3
Quizás agregaría que el flujo del código de autorización permite a los clientes almacenar los tokens y reutilizarlos. En el flujo implícito, no siempre tiene esa opción y, como tal, el flujo implícito es una elección pragmática entre el nivel de seguridad y la conveniencia.
PålOliver

2
Esto responde solo a la mitad y "¿qué se ha perdido"?
EralpB

3
No creo que esta sea una respuesta integral, el flujo implícito no pretende obtener ventajas en la simplicidad sino comprometer las preocupaciones de seguridad con la aplicación del lado del cliente. Auth code, junto con client_idy client_secretse utilizan para identificar clientes confiables que pueden actualizar tokens para un inicio de sesión prolongado y para "inicio de sesión sin conexión" . Sin embargo, en una aplicación del lado del cliente, no hay forma de registrar a cada cliente, de ahí el tipo de concesión implícita "simplificada" para el acceso temporal a la información del usuario
Chen Xie

1
La inclusión del secreto del cliente no solo hace que el flujo sea más complejo, sino que lo hace menos seguro . El secreto del cliente no es un secreto si necesita ser enumerado dentro del código del lado del cliente y, por lo tanto, estaría expuesto a Internet. Si su ID de cliente solo se usa en flujos implícitos, esto no es un problema. Pero si también se usa en otra parte de su plataforma para token de actualización o otorgamiento de códigos de autorización, entonces exponer el secreto correspondiente es un gran problema.
Ataraxia

94

Está ahí por razones de seguridad, no por simplicidad.

Debe considerar la diferencia entre el agente de usuario y el cliente :

El agente de usuario es el software mediante el cual el usuario ("propietario del recurso") se comunica con otras partes del sistema (servidor de autenticación y servidor de recursos).

El cliente es el software que desea acceder a los recursos del usuario en el servidor de recursos.

En el caso de cliente-agente y cliente desacoplados, la concesión del código de autorización tiene sentido. Por ejemplo, el usuario utiliza un navegador web (agente de usuario) para iniciar sesión con su cuenta de Facebook en Kickstarter. En este caso, el cliente es uno de los servidores de Kickstarter, que maneja los inicios de sesión de los usuarios. Este servidor obtiene el token de acceso y el token de actualización de Facebook. Por lo tanto, este tipo de cliente se considera "seguro", debido al acceso restringido, los tokens se pueden guardar y Kickstarter puede acceder a los recursos de los usuarios e incluso actualizar los tokens de acceso sin interacción del usuario.

Si el agente de usuario y el cliente están acoplados (por ejemplo, aplicación móvil nativa, aplicación javascript), se puede aplicar el flujo de trabajo de autorización implícita . Se basa en la presencia del propietario del recurso (para ingresar las credenciales) y no admite tokens de actualización. Si este cliente almacena el token de acceso para su uso posterior, será un problema de seguridad, ya que el token puede ser extraído fácilmente por otras aplicaciones o usuarios del cliente. La ausencia del token de actualización es una pista adicional, que este método no está diseñado para acceder a los recursos del usuario en ausencia del usuario.


2
Veo que mi navegador ha iniciado sesión en mi cuenta de Google durante meses. Entonces, ¿Google usa el token de acceso en el navegador o un token de acceso con un tiempo de vencimiento largo? ¿Qué diferencia de uso entre el token de acceso con un tiempo de vencimiento largo y el token de acceso? cualquier otro cliente puede capturar el token de acceso y usarlo cuando el propietario del recurso no está presente.
Mohammad Nikravan

¿Supongo que te refieres a la diferencia entre el token de actualización y el token de acceso con un tiempo de vencimiento largo ? El token de actualización no debe guardarse en escenarios inseguros, pero puede guardar su token de acceso (por ejemplo, en el almacenamiento local del navegador). La seguridad se logra manteniendo la vida útil de su token de acceso lo más baja posible, aunque aún sea cómoda para sus usuarios (por ejemplo, puede cerrar sesión automáticamente después de x minutos de inactividad). Si usa tokens de acceso de larga duración, prácticamente hace que los tokens de actualización sean obsoletos.
artkoenig

Gracias por su explicación, pero también tengo otra confusión. No entiendo por qué necesitamos el flujo del "Código de autorización". Podemos alcanzar el mismo resultado en el servidor mediante flujo implícito (access_token) y un token de actualización. Parece que la única consideración de seguridad del flujo implícito es que el código de acceso debe tener una vida corta, por lo que no se puede usar de servidor a servidor. OK, pero el token de actualización resuelve este problema. ¿Por qué deberíamos usar un flujo auth_code y solicitar access_token por ese token en un servidor para obtener access_code mientras podemos lograr el mismo resultado con refresh_token?
Mohammad Nikravan el

"el token puede ser extraído fácilmente por otras aplicaciones" ¿Cómo?
mvmn

@MohammadNikravan busque la respuesta en stackoverflow.com/q/13387698/355438
Lu55

60

La explicación habitual es que la concesión implícita es más fácil de implementar cuando está utilizando un cliente JavaScript. Pero creo que esta es la forma incorrecta de verlo. Si está utilizando un cliente JavaScript que solicita recursos protegidos directamente a través de XMLHttpRequest, la concesión implícita es su única opción, aunque es menos segura. *

La concesión del Código de autorización proporciona seguridad adicional, pero solo funciona cuando tiene un servidor web que solicita los recursos protegidos. Dado que el servidor web puede almacenar el token de acceso, corre menos riesgo de que el token de acceso esté expuesto a Internet, y puede emitir un token que dura mucho tiempo. Y dado que el servidor web es de confianza, se le puede dar un "token de actualización", para que pueda obtener un nuevo token de acceso cuando caduque el anterior.

Pero, y este es un punto fácil de pasar por alto, la seguridad del flujo del código de Autorización funciona solo si el servidor web está protegido con una sesión, que se establece con la autenticación del usuario (inicio de sesión). Sin una sesión, un usuario que no sea de confianza solo podría realizar solicitudes al servidor web, utilizando client_id, y sería lo mismo que si el usuario tuviera el token de acceso. Agregar una sesión significa que solo un usuario autenticado puede acceder a los recursos protegidos. Client_id es solo la "identidad" de la aplicación web JS, no la autenticación de dicha aplicación web.

También significa que puede finalizar la sesión antes de que caduque el token OAuth. No hay una forma estándar de invalidar un token de acceso. Pero si su sesión caduca, el token de acceso es inútil, ya que nadie lo sabe excepto el servidor web. Si un usuario que no es de confianza obtuvo acceso a su clave de sesión, solo podrá acceder a los recursos protegidos mientras la sesión sea válida.

Si no hay un servidor web, debe usar la concesión implícita. Pero esto significa que el token de acceso está expuesto a Internet. Si un usuario no confiable obtiene acceso a él, puede usarlo hasta que caduque. Esto significa que tendrán acceso a él por más tiempo que con una subvención del Código de autorización. Por lo tanto, es posible que desee considerar hacer que el token caduque antes y evitar dar acceso a recursos más confidenciales.

* EDITAR: más recientemente, las personas recomiendan que evites usar la concesión implícita, incluso en aplicaciones web sin un servidor. En su lugar, puede usar la concesión de Código de autorización configurada con un secreto vacío, junto con PKCE. La concesión de código de autenticación evita almacenar el token de acceso en el historial de su navegador, y PKCE evita exponerlo si alguien secuestra la URL de redireccionamiento para robar el código de autenticación. En este caso, necesitará que el servidor evite devolver un token de actualización, ya que su cliente probablemente no pueda almacenarlo de forma segura. Y debería emitir un token de acceso con las mismas limitaciones mencionadas anteriormente.


21

Se reduce a: si un usuario está ejecutando una aplicación web (JavaScript) basada en navegador o "pública" sin componente del lado del servidor, entonces el usuario confía implícitamente en la aplicación (y el navegador donde se ejecuta, potencialmente con otro navegador basadas en aplicaciones ...).

No hay un servidor remoto de terceros, solo el servidor de recursos. No hay ningún beneficio en un código de autorización, porque no hay otro agente además del navegador que actúe en nombre del usuario. No hay beneficio para las credenciales del cliente por la misma razón. ( Cualquier cliente puede intentar usar este flujo).

Las implicaciones de seguridad, sin embargo, son significativas. De http://tools.ietf.org/html/rfc6749#section-10.3 :

Cuando se utiliza el tipo de concesión implícita, el token de acceso se transmite en el fragmento de URI, lo que puede exponerlo a terceros no autorizados.

De http://tools.ietf.org/html/rfc6749#section-10.16 :

El propietario de un recurso puede delegar voluntariamente el acceso a un recurso al otorgar un token de acceso al cliente malicioso de un atacante. Esto puede deberse a phishing o algún otro pretexto ...


¿Qué quiere decir con "público", aplicación web (JavaScript) sin componente del lado del servidor? ¿Cómo puede haber una aplicación web sin servidor?
Zammy Page

2
@ZammyPage, esto sería lo que a menudo se llama una aplicación de página única (SPA). La totalidad de la aplicación se sirve desde un recurso estático. Javascript en la aplicación accede dinámicamente a los recursos que necesita, en cualquier servidor de recursos al que pueda acceder. No hay ningún servidor que genere el contenido del cliente: el javascript en el cliente modifica el DOM según sea necesario para representar los recursos a los que ha accedido.
Elroy Flynn

13

No estoy seguro de entender correctamente la respuesta y el comentario de Dan. Me parece que la respuesta ha declarado algunos hechos correctos, pero señala exactamente lo que OP preguntó. Si entiendo correctamente, la principal ventaja del flujo de concesión implícito es que un cliente como la aplicación JS (por ejemplo, la extensión de Chrome) no tiene que exponer el secreto del cliente.

Dan Taflin dijo:

... en el flujo del código de autorización, el propietario del recurso nunca necesita ver el token de acceso, mientras que en los clientes de JavaScript eso es inevitable. Sin embargo, el secreto del cliente aún se podía guardar de los clientes de JavaScript utilizando el flujo de código de autorización

Quizás te haya entendido mal, pero el cliente (aplicación JS en este caso) debe pasar la credencial del cliente (clave y secreto del cliente) al servidor de recursos en el flujo del código de autorización, ¿verdad? El secreto del cliente no se puede "guardar de JS".


66
Me doy cuenta de que esta es una vieja pregunta, pero esta es una mejor respuesta que la aceptada. La razón por la que existe la concesión implícita es que un cliente javascript no puede guardar un secreto y, por lo tanto, no puede autenticarse. Por lo tanto, el servidor de autorización debe confiar únicamente en el registro de uri de redireccionamiento y el agente de usuario para la seguridad. Pasas tokens de autorización solo al agente de usuario, y solo a una uri de redireccionamiento específica, teóricamente evitando la intercepción (porque un usuario malintencionado que no posee el dominio de la uri de redireccionamiento no puede ejecutar código en el agente de usuario en esa uri).
Gregates

De hecho, la respuesta aceptada me confundió. ¡Me hizo pensar que entendí mal lo que es client_secret! Esta respuesta y el comentario anterior son acertados.
Zarzaparrilla

9

Si bien la concesión implícita se diseñó para admitir aplicaciones que no podían proteger el secreto de un cliente, incluidas las aplicaciones JavaScript del lado del cliente, algunos proveedores están implementando una alternativa que utiliza el código de autorización sin un secreto de cliente. El OAuth 2.0 IETF RFC-6749 se publicó en 2012 y las recomendaciones actuales son algunas de las discusiones recientes de 2017.

La discusión de 2017 sobre la lista de correo IETF OAuth está disponible en estos implementadores:

Leer más aquí:

Implícito se recomendó anteriormente para clientes sin secreto, pero se ha reemplazado mediante el uso de la concesión del Código de autorización sin secreto.

...

Anteriormente, se recomendaba que las aplicaciones basadas en navegador utilizaran el flujo "implícito", que devuelve un token de acceso inmediatamente y no tiene un paso de intercambio de token. En el tiempo transcurrido desde que la especificación se escribió originalmente, las mejores prácticas de la industria han cambiado para recomendar que se use el flujo del código de autorización sin el secreto del cliente. Esto proporciona más oportunidades para crear un flujo seguro, como el uso del parámetro de estado. Referencias: Redhat , Deutsche Telekom , Smart Health IT .

Aquí también se menciona el paso a Código de autenticación sin secreto de cliente desde Grant implícito para aplicaciones móviles:


Creo que quieres tener cuidado con esta recomendación. Esto se recomendó en la guía para aplicaciones nativas, en lugar de spas. Desafortunadamente, no hay una buena guía sobre los SPA como se documenta en muchas de las discusiones en línea, foros e incluso en la lista de correo oauth-wg.
Tom

La recomendación de pasar al código de autenticación sin secreto de la concesión implícita es una recomendación tanto para los SPA como para las aplicaciones móviles, pero mi extracto anterior es específico para los SPA. El artículo al que se hace referencia usa texto similar tanto para los SPA como para las aplicaciones móviles, pero con el lenguaje "aplicaciones basadas en navegador" "aplicaciones móviles y nativas" en el texto respectivo. Además, las referencias para Redhat, DT, Smart Health IT, son específicas de los SPA y no están incluidas en la nota para aplicaciones móviles. Agregué un enlace profundo a los SPA en la respuesta para que sea más fácil de encontrar. Por favor, publique algunos enlaces a las discusiones que menciona.
Grokify

Una discusión bastante reciente (2018) oauth-wg se puede encontrar aquí ietf.org/mail-archive/web/oauth/current/msg18020.html . RFC 8252 es para aplicaciones nativas ya que el título sugiere "OAuth 2.0 para aplicaciones nativas". Las referencias a Redhat, DT, Smart Health IT son respuestas a una discusión de la lista de correo, no un rfc, borrador de trabajo, etc ...
Tom

3

Además de las otras respuestas, también es importante darse cuenta de que el perfil implícito permite un flujo de solo canal frontal en lugar del flujo del código de autorización que requiere una llamada al servidor de autorización; Esto se hace evidente en OpenID Connect, que es un protocolo SSO construido sobre Auth 2.0 donde el flujo implícito se asemeja al enlace SAML POST bastante popular y el flujo del código de autorización se asemeja al enlace de artefactos SAML menos implementado


3

En el flujo implícito, si el navegador del usuario está dañado (extensión / virus malvado), entonces la corrupción obtiene acceso a los recursos del usuario y puede hacer las cosas malas.

En el flujo de autenticación, la corrupción no puede porque no conoce el secreto del cliente.


2

https://tools.ietf.org/html/rfc6749#page-8

Implícito

La concesión implícita es un flujo de código de autorización simplificado optimizado para clientes implementados en un navegador que utiliza un lenguaje de script como JavaScript. En el flujo implícito, en lugar de emitir al cliente un código de autorización, al cliente se le emite un token de acceso directamente (como resultado de la autorización del propietario del recurso). El tipo de concesión es implícito, ya que no se emiten credenciales intermedias (como un código de autorización) (y luego se utilizan para obtener un token de acceso).

Al emitir un token de acceso durante el flujo de concesión implícito, el
servidor de autorización no autentica al cliente. En algunos
casos, la identidad del cliente se puede verificar a través del URI de redireccionamiento
utilizado para entregar el token de acceso al cliente. El token de acceso puede estar expuesto al propietario del recurso u otras aplicaciones con acceso al agente de usuario del propietario del recurso.

Las subvenciones implícitas mejoran la capacidad de respuesta y la eficiencia de algunos
clientes (como un cliente implementado como una aplicación en el navegador),
ya que reduce la cantidad de viajes de ida y vuelta necesarios para obtener un
token de acceso.


1

Creo que Will Cain respondió esto cuando dijo "No hay ningún beneficio para las credenciales del cliente por la misma razón. (Cualquier cliente puede intentar usar este flujo)." También considere que el redirect_uri para flujo implícito puede ser "localhost" - sin devolución de llamada se realiza desde el servidor de autorización para el flujo implícito. Como no hay forma de confiar previamente en el cliente, el usuario tendría que aprobar la liberación de las reclamaciones del usuario.


1

La concesión implícita permite obtener tokens del punto final de autorización con a GET. Esto significa que el servidor de autorización no tiene que admitir CORS.

Si eso no es una preocupación y no hay otros problemas relacionados con el servidor de autorización inflexible (por ejemplo, los tokens de actualización no son opcionales, por alguna razón), el flujo de código de autorización es el preferido, incluso para clientes públicos, de acuerdo con las tendencias recientes de la industria y al menos a esta (actual) instancia de un borrador oficial .

Históricamente, hubo otras razones para implementar el flujo implícito, pero parece que actualmente son superadas por las ventajas de seguridad que brinda la concesión del código de autorización, que incluyen:

  • opción de entregar y usar los tokens en un canal posterior para clientes confidenciales
  • no exponer tokens en el historial del navegador para clientes públicos
  • interrumpir un flujo no autorizado antes de emitir tokens - con PKCE , para "todo tipo de clientes OAuth"

0

Acabo de enfrentar un artículo sobre OAuth 2.0. El autor afirma que la razón detrás del flujo implícito es que las aplicaciones JS estaban muy restringidas en sus solicitudes:

Si se pregunta por qué el tipo implícito se incluyó en OAuth 2.0, la explicación es simple: la misma política de origen. En aquel entonces, las aplicaciones frontend no podían enviar solicitudes a diferentes hosts para obtener el token de acceso mediante código. Hoy tenemos CORS (Cross-Origin Resource Sharing).

https://medium.com/securing/what-is-going-on-with-oauth-2-0-and-why-you-should-not-use-it-for-authentication-5f47597b2611

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.