¿Cuál es el flujo de OAuth 2.0 correcto para una aplicación móvil?

87

Estoy intentando implementar la autorización delegada en una API web para aplicaciones móviles usando OAuth 2.0. Según la especificación, el flujo de concesión implícito no admite tokens de actualización, lo que significa que una vez que se otorga un token de acceso durante un período de tiempo específico, el usuario debe otorgar permisos a la aplicación nuevamente una vez que el token expira o se revoca.

Supongo que este es un buen escenario para algún código javascript que se ejecuta en un navegador, como se menciona en la especificación. Estoy tratando de minimizar las veces que el usuario debe otorgar permisos a la aplicación para obtener un token, por lo que parece que el flujo del Código de autorización es una buena opción, ya que admite tokens de actualización.

Sin embargo, este flujo parece depender en gran medida de un navegador web para realizar las redirecciones. Me pregunto si este flujo sigue siendo una buena opción para una aplicación móvil si se utiliza un navegador web integrado. ¿O debería seguir el flujo implícito?

Pablo Cibraro
fuente
1
La pregunta sería: ¿es como la máxima prioridad que el usuario nunca tenga que volver a escribir una contraseña después del primer inicio de sesión?
privilegio mínimo
Sí, ese es exactamente mi requisito. El usuario debe escribir la contraseña una sola vez. Sin embargo, no quiero configurar un token con una vida útil infinita y mantenerlo en la aplicación móvil, ya que eso iría en contra de la capacidad de revocar el token. (A menos que agregue algo de lógica en la aplicación móvil para detectar que la solicitud no fue autorizada, por lo que solicito un nuevo token después de eso)
Pablo Cibraro
1
Puede agregar un token con una vida útil infinita y aún así revocarlo. Y sí, la lógica de la aplicación debería poder detectar eso. RFC 6750 define una forma de verificar si el error se debe a un token revocado.
Pedro Felix
1
Evite las vistas web (a menos que sea propietario de la pila completa y no esté utilizando el inicio de sesión social) que abren la posibilidad de comprometer las contraseñas. Cuando un agente de usuario integrado de un tercero me solicita las credenciales, desinstalo la aplicación. Algunas API ahora incluso prohíben integraciones como esta dev.fitbit.com/docs/oauth2 He proporcionado otra respuesta para aclarar aún más algunos de estos conceptos ( stackoverflow.com/a/38582630/752167 )
Matt C

Respuestas:

90

Aclaración: Aplicación móvil = Aplicación nativa

Como se indica en otros comentarios y en algunas fuentes en línea, lo implícito parece un ajuste natural para las aplicaciones móviles, sin embargo, la mejor solución no siempre es clara (y de hecho, lo implícito no se recomienda por las razones que se analizan a continuación).

Prácticas recomendadas de OAuth2 para aplicaciones nativas

Cualquiera que sea el enfoque que elija (hay algunas compensaciones a considerar), debe prestar atención a las mejores prácticas que se describen aquí para las aplicaciones nativas que usan OAuth2: https://tools.ietf.org/html/rfc8252

Considere las siguientes opciones

Implícito

¿Debo usar implícito?

Para citar de la Sección 8.2 https://tools.ietf.org/html/rfc8252#section-8.2

El flujo de autorización de concesión implícita de OAuth 2.0 (definido en la Sección 4.2 de OAuth 2.0 [RFC6749]) generalmente funciona con la práctica de realizar la solicitud de autorización en el navegador y recibir la respuesta de autorización a través de la comunicación entre aplicaciones basada en URI.
Sin embargo, como el flujo implícito no puede ser protegido por PKCE [RFC7636] (que se requiere en la Sección 8.1), NO SE RECOMIENDA el uso del flujo implícito con aplicaciones nativas. .

Los tokens de acceso otorgados a través del flujo implícito tampoco se pueden actualizar sin la interacción del usuario, lo que hace que el flujo de concesión del código de autorización, que puede emitir tokens de actualización, sea la opción más práctica para las autorizaciones de aplicaciones nativas que requieren la actualización de los tokens de acceso.

Código de Autorización

Si opta por el Código de autorización, entonces un enfoque sería utilizar un proxy a través de su propio componente de servidor web que enriquece las solicitudes de token con el secreto del cliente para evitar almacenarlo en la aplicación distribuida en los dispositivos.

Extracto a continuación de: https://dev.fitbit.com/docs/oauth2/

El flujo de concesión del código de autorización se recomienda para aplicaciones que tienen un servicio web. Este flujo requiere una comunicación de servidor a servidor utilizando el secreto de cliente de una aplicación.

Nota: Nunca ponga su secreto de cliente en código distribuido, como aplicaciones descargadas a través de una tienda de aplicaciones o JavaScript del lado del cliente.

Las aplicaciones que no tienen un servicio web deben utilizar el flujo de concesión implícita.

Conclusión

La decisión final debe tener en cuenta su experiencia de usuario deseada, pero también su apetito por el riesgo después de realizar una evaluación de riesgo adecuada de los enfoques seleccionados y comprender mejor las implicaciones.

Una gran lectura está aquí https://auth0.com/blog/oauth-2-best-practices-for-native-apps/

Otro es https://www.oauth.com/oauth2-servers/oauth-native-apps/ que dice

La mejor práctica actual de la industria es utilizar el flujo de autorización mientras se omite el secreto del cliente y utilizar un agente de usuario externo para completar el flujo. Un agente de usuario externo suele ser el navegador nativo del dispositivo (con un dominio de seguridad separado de la aplicación nativa), de modo que la aplicación no puede acceder al almacenamiento de cookies o inspeccionar o modificar el contenido de la página dentro del navegador.

Consideración PKCE

También debe considerar PKCE que se describe aquí https://www.oauth.com/oauth2-servers/pkce/

Específicamente, si también está implementando el servidor de autorización, https://www.oauth.com/oauth2-servers/oauth-native-apps/checklist-server-support-native-apps/ indica que debe

  • Permita que los clientes registren esquemas de URL personalizados para sus URL de redireccionamiento.
  • Admite URL de redireccionamiento de IP de bucle invertido con números de puerto arbitrarios para admitir aplicaciones de escritorio.
  • No asuma que las aplicaciones nativas pueden guardar un secreto. Exija que todas las aplicaciones declaren si son públicas o confidenciales, y solo emita secretos de cliente para aplicaciones confidenciales.
  • Admite la extensión PKCE y requiere que los clientes públicos la utilicen.
  • Intente detectar cuándo la interfaz de autorización está integrada en la vista web de una aplicación nativa, en lugar de iniciarse en un navegador del sistema, y ​​rechace esas solicitudes.

Consideración de vistas web

Hay muchos ejemplos en la naturaleza que usan vistas web, es decir, un agente de usuario integrado, pero este enfoque debe evitarse (especialmente cuando la aplicación no es propia) y, en algunos casos, puede resultar en que se le prohíba el uso de una API como extracto abajo de aquí demuestra

Cualquier intento de insertar la página de autenticación de OAuth 2.0 resultará en que tu aplicación sea prohibida en la API de Fitbit.

Por motivos de seguridad, la página de autorización de OAuth 2.0 debe presentarse en una vista de navegador dedicada. Los usuarios de Fitbit solo pueden confirmar que se están autenticando con el sitio original de Fitbit.com si tienen las herramientas proporcionadas por el navegador, como la barra de URL y la información del certificado Transport Layer Security (TLS).

Para las aplicaciones nativas, esto significa que la página de autorización debe abrirse en el navegador predeterminado. Las aplicaciones nativas pueden usar esquemas de URL personalizados como URI de redireccionamiento para redirigir al usuario desde el navegador a la aplicación que solicita permiso.

Las aplicaciones de iOS pueden usar la clase SFSafariViewController en lugar de cambiar la aplicación a Safari. Está prohibido el uso de la clase WKWebView o UIWebView.

Las aplicaciones de Android pueden usar pestañas personalizadas de Chrome en lugar de cambiar la aplicación al navegador predeterminado. Está prohibido el uso de WebView.

Para aclarar aún más, aquí hay una cita de esta sección de un borrador anterior del enlace de mejores prácticas proporcionado anteriormente.

Los agentes de usuario integrados, comúnmente implementados con vistas web, son un método alternativo para autorizar aplicaciones nativas. Sin embargo, por definición, no son seguros para su uso por parte de terceros. Implican que el usuario inicie sesión con sus credenciales de inicio de sesión completas, solo para que se reduzcan a credenciales OAuth menos potentes.

Incluso cuando los utilizan aplicaciones de origen confiables, los agentes de usuario integrados violan el principio de privilegios mínimos al obtener credenciales más poderosas de las que necesitan, lo que potencialmente aumenta la superficie de ataque.

En implementaciones típicas basadas en vista web de agentes de usuario integrados, la aplicación host puede: registrar cada pulsación de tecla ingresada en el formulario para capturar nombres de usuario y contraseñas; enviar formularios automáticamente y omitir el consentimiento del usuario; copiar cookies de sesión y utilizarlas para realizar acciones autenticadas como usuario.

Alentar a los usuarios a ingresar credenciales en una vista web incrustada sin la barra de direcciones habitual y otras características de identidad que tienen los navegadores hace que sea imposible para el usuario saber si están iniciando sesión en el sitio legítimo, e incluso cuando lo están, los capacita que está bien ingresar credenciales sin validar el sitio primero.

Aparte de las preocupaciones de seguridad, las vistas web no comparten el estado de autenticación con otras aplicaciones o el navegador del sistema, lo que requiere que el usuario inicie sesión para cada solicitud de autorización y conduce a una mala experiencia de usuario.

Debido a lo anterior, NO SE RECOMIENDA el uso de agentes de usuario integrados, excepto cuando una aplicación de origen confiable actúa como el agente de usuario externo para otras aplicaciones o proporciona inicio de sesión único para varias aplicaciones de origen.

Los servidores de autorización DEBERÍAN considerar tomar medidas para detectar y bloquear inicios de sesión a través de agentes de usuario integrados que no sean los suyos, siempre que sea posible.

Aquí también se plantean algunos puntos interesantes: /security/179756/why-are-developers-using-embedded-user-agents-for-3rd-party-auth-what-are-the- una

Matt C
fuente
3
Google eliminará la compatibilidad con vistas web el 20 de abril de 2017 developers.googleblog.com/2016/08/…
Matt C
Para su información, las referencias del documento al comienzo de esta respuesta si ya no es un borrador OAuth 2.0 para aplicaciones nativas - tools.ietf.org/html/rfc8252
Kostiantyn Sokolinskyi
Gracias @KostiantynSokolinskyi, editado en consecuencia con el enlace para rfc que ya no es un borrador
Matt C
@MattC ¿Cuál es la mejor manera de implementar el registro de un nuevo usuario? ¿Debemos hacerlo dentro de la aplicación o en el IDP? ¿Es posible iniciar sesión automáticamente en el registro posterior del usuario? stackoverflow.com/questions/60187173/…
Yashvit
Lo siento, estoy confundido acerca de algunos detalles ... ¿Podrías echar un vistazo? ¡Gracias! enlace ---> stackoverflow.com/q/61313694/4619958
ch271828n
25

Desafortunadamente, no creo que haya una respuesta clara a esta pregunta. Sin embargo, estas son las opciones que he identificado:

  • Si está bien pedirle al usuario sus credenciales, utilice las Credenciales de contraseña del propietario del recurso . Sin embargo, esto puede no ser posible por algunas razones, a saber

    • Las políticas de usabilidad o seguridad prohíben la inserción de la contraseña directamente en la aplicación.
    • El proceso de autenticación se delega en un proveedor de identidad externo y debe realizarse a través de un flujo basado en redirecciones HTTP (por ejemplo, OpenID, SAMLP o WS-Federation)
  • Si se requiere el uso de un flujo basado en navegador, utilice el flujo de código de autorización . Aquí, la definición de redirect_uries un gran desafío, para el cual existen las siguientes opciones:

    • Utilice la técnica descrita en https://developers.google.com/accounts/docs/OAuth2InstalledApp , donde un especial redirect_uri(p. Ej.urn:ietf:wg:oauth:2.0:oob . ) Indica al extremo de autorización que muestre el código de autorización en lugar de redirigirlo a la aplicación cliente. El usuario puede copiar manualmente este código o la aplicación puede intentar obtenerlo del título del documento HTML.
    • Utilizar un localhost servidor en el dispositivo (la gestión de puertos puede no ser fácil).
    • Utilice un esquema de URI personalizado (por ejemplo myapp://...) que cuando se desreferencia activa un "controlador" registrado (los detalles dependen de la plataforma móvil).
    • Si está disponible, utilice una "vista web" especial, como WebAuthenticationBroker en Windows 8, para controlar y acceder a las respuestas de redirección HTTP.

Espero que esto ayude

Pedro

Pedro Félix
fuente
¡Gracias Pedro por el aporte !. Sí, parece que el flujo de código de autorización con el esquema de URI personalizado o la vista web parece ser la mejor opción aquí.
Pablo Cibraro
1
Todo depende de si desea que el cliente escriba la contraseña en una vista web o en la aplicación del cliente. Si es posible, preferiría la aplicación del cliente, luego intercambiar inmediatamente el secreto con un token de acceso / actualización.
privilegio mínimo
¡Gracias Dominick !. Mi cliente está usando ADFS para autenticar a los usuarios, por lo que quieren ingresar las credenciales en la página de inicio de sesión. La vista web funcionará para ellos
Pablo Cibraro
5
Tengo curiosidad por saber por qué recomendaría el "flujo de código de autorización". ¿No necesitaría client_secret y client_id para intercambiar el código por un access_token? Pensé que el flujo "implícito" fue diseñado para estos escenarios, porque no requiere que se almacenen secretos en el dispositivo.
Eugenio Pace
1
implícito no admite tokens de actualización OOB. En el escenario de Pablo, claramente recomendaría el flujo de RO. Parece que la empresa implementó aplicaciones en el mismo backend de la empresa.
privilegio mínimo
9

TL; DR: Use la concesión del código de autorización con PKCE

1. Tipo de subvención implícita

El tipo de subvención implícita es bastante popular entre las aplicaciones móviles. Pero no estaba destinado a usarse así. Existen preocupaciones de seguridad en torno a la redirección. Justin Richer afirma :

El problema surge cuando se da cuenta de que, a diferencia de la URL de un servidor remoto, no existe una forma confiable de garantizar que se respete el enlace entre un URI de redireccionamiento determinado y una aplicación móvil específica. Cualquier aplicación en el dispositivo puede intentar insertarse en el proceso de redireccionamiento y hacer que sirva el URI de redireccionamiento. Y adivina qué: si usaste el flujo implícito en tu aplicación nativa, entonces le entregaste al atacante tu token de acceso. No hay recuperación desde ese punto, tienen el token y pueden usarlo.

Y junto con el hecho de que no te deja refrescar el token de acceso, mejor evitarlo.

2. Código de autorización Tipo de concesión

La concesión del código de autorización requiere un secreto de cliente. Pero no debe almacenar información confidencial en el código fuente de su aplicación móvil. La gente puede extraerlos. Para no exponer el secreto del cliente, debe ejecutar un servidor como intermediario como Facebook escribe :

Recomendamos que los tokens de acceso a la aplicación solo se utilicen directamente desde los servidores de su aplicación para brindar la mejor seguridad. Para las aplicaciones nativas, sugerimos que la aplicación se comunique con su propio servidor y el servidor luego realice las solicitudes de API a Facebook utilizando el token de acceso a la aplicación.

No es una solución ideal, pero hay una manera nueva y mejor de hacer OAuth en dispositivos móviles: clave de prueba para intercambio de código

3. Tipo de concesión de código de autorización con PKCE (clave de prueba para intercambio de código)

Fuera de las limitaciones, se creó una nueva técnica que le permite usar el Código de autorización sin un secreto de cliente. Puede leer el RFC 7636 completo o esta breve introducción .

PKCE (RFC 7636) es una técnica para proteger a los clientes públicos que no utilizan un secreto de cliente.

Es utilizado principalmente por aplicaciones nativas y móviles, pero la técnica también se puede aplicar a cualquier cliente público. Requiere soporte adicional por parte del servidor de autorización, por lo que solo es compatible con ciertos proveedores.

de https://oauth.net/2/pkce/

Filtro de Johannes
fuente
-3

El uso de una vista web en su aplicación móvil debería ser una forma asequible de implementar el protocolo OAuth2.0 en la plataforma Android.

En cuanto al campo redirect_uri, creo que http://localhostes una buena opción y no tiene que portar un servidor HTTP dentro de su aplicación, porque puede anular la implementación de la onPageStartedfunción en la WebViewClientclase y dejar de cargar la página web http://localhostdespués de verificar el urlparámetro.

public void onPageStarted(final WebView webView, final String url,
        final Bitmap favicon) {}
Céfiro
fuente
3
Mejores prácticas para aplicaciones nativas que utilizan OAuth2: tools.ietf.org/html/draft-wdenniss-oauth-native-apps
Matt C
1
Como dijo Matt C, arriba. Las vistas web son una mala idea para las aplicaciones móviles: son inseguras, permiten que la aplicación obtenga acceso a las credenciales (por lo que no son más seguras que RO) y no permiten a los usuarios verificar el dominio y los certificados TLS. Use el tipo de concesión de código de autenticación con un controlador de URI personalizado y asegúrese de que está usando el código de prueba para el intercambio de claves (PKCE) para evitar que las aplicaciones maliciosas en su teléfono intercepten el código de autenticación y obtengan acceso a su API.
ChrisC
2
La versión actualizada del borrador del documento de mejores prácticas de OAuth 2.0 para aplicaciones nativas se encuentra en tools.ietf.org/html/draft-ietf-oauth-native-apps
Jeff Olson
-4

La experiencia de usuario más fluida para la autenticación y la más fácil de implementar es incrustar una vista web en su aplicación. Procese las respuestas recibidas por la vista web desde el punto de autenticación y detecte el error (cancelación del usuario) o la aprobación (y extraiga el token de los parámetros de consulta de la URL). Y creo que puedes hacerlo en todas las plataformas. He logrado que esto funcione para lo siguiente: ios, android, mac, aplicaciones de Windows Store 8.1, aplicación de Windows Phone 8.1. Hice esto para los siguientes servicios: dropbox, google drive, onedrive, box, basecamp. Para las plataformas que no son de Windows, estaba usando Xamarin, que supuestamente no expone todas las API específicas de la plataforma, pero sí expone lo suficiente para hacer esto posible. Así que es una solución bastante accesible, incluso desde una perspectiva multiplataforma, y ​​no

Radu Simionescu
fuente
Si bien brindamos una experiencia de usuario conveniente, veremos que la industria se aleja de este enfoque. Dado que las vistas web abren la posibilidad de comprometer las contraseñas, cuando un agente de usuario integrado me solicita las credenciales, desinstalo la aplicación. Algunas API ahora incluso prohíben integraciones como esta dev.fitbit.com/docs/oauth2
Matt C
Mejores prácticas para aplicaciones nativas que utilizan OAuth2: tools.ietf.org/html/draft-wdenniss-oauth-native-apps
Matt C
No veo cómo podría un servicio habilitado por Oauth prohibir este enfoque. Es indetectable y seguro ... Algunos servicios habilitados para oauth proporcionan clientes específicos de la plataforma para facilitar la autenticación, y dichos clientes realmente hacen lo que he descrito aquí (mostrar una vista web incrustada y realizar un seguimiento de los cambios de URL). La mejor práctica que vinculó recomienda lo mismo: use el navegador del sistema o la vista web incorporada. ¿Qué argumento ataca con mi respuesta? no está claro.
Radu Simionescu
Sin intención de ataque, solo resaltando el problema. El enlace dice que existen los 2 enfoques que mencionas, pero solo un agente de usuario externo puede considerarse seguro, específicamente dice que las opciones para las aplicaciones nativas son "a través de un agente de usuario integrado o un agente de usuario externo. Este documento recomienda aplicaciones externas A los agentes de usuario les gustan las pestañas del navegador en la aplicación como la única opción segura y utilizable para OAuth ".
Matt C
Cita adicional "En implementaciones típicas basadas en vista web de agentes de usuario integrados, la aplicación de host puede: registrar cada pulsación de tecla ingresada en el formulario para capturar nombres de usuario y contraseñas; enviar formularios automáticamente y omitir el consentimiento del usuario" ....... "NO SE RECOMIENDA el uso de agentes de usuario integrados, excepto cuando una aplicación de origen confiable actúa como agente de usuario externo para otras aplicaciones o proporciona un inicio de sesión único para varias aplicaciones de origen. Los servidores de autorización DEBEN considerar la posibilidad de tomar medidas para detectar y bloquear los inicios de sesión a través de agentes de usuario integrados que no son los suyos, cuando sea posible ".
Matt C