Autenticación con OAuth2 para una aplicación * y * un sitio web

Estoy desarrollando un sitio web que se accede principalmente a través de una aplicación, y quiero usar OAuth2 para el registro y la autenticación del usuario. Puesto que es una aplicación de Android, empezaré a usar las cosas de OAuth2 de Google, ya que proporciona una interfaz de usuario decente en Android.

Google afirma que "puede elegir usar el sistema de autenticación de Google como una forma de externalizar la autenticación de usuarios para su aplicación. Esto puede eliminar la necesidad de crear, mantener y proteger un almacén de nombre de usuario y contraseña". Que es lo que quiero hacer. Sin embargo, cuando reviso todos sus ejemplos y lo que sea, solo puedo encontrar información sobre cómo tener un sitio web o una aplicación para autenticar a un usuario en contra de los servicios de Google.

Y de hecho, cuando voy a registrar mi aplicación ("cliente") con OAuth2 de Google hay opciones para clientes de sitios web y clientes "instalados" (es decir, una aplicación para móviles) pero no para ambos. Puedo crear dos clientes separados, pero leo el borrador de OAuth2 y creo que habrá un problema, el cual explicaré ahora.

Así es como lo vi trabajar:

Diagrama de flujo OAuth2

  1. El usuario pide a MyApp que acceda a sus datos privados.
  2. La aplicación utiliza la clase AccountManager de Android para solicitar un token de acceso para las API de Google.
  3. Android dice al usuario "La aplicación 'MyApp' quiere tener acceso a tu Información Básica en Google. ¿Está esto bien?"
  4. El usuario dice que sí.
  5. AccountManager conecta al servidor OAuth2 de Google usando las credenciales almacenadas en el teléfono y solicita un token de acceso.
  6. Se devuelve el token de acceso (que sigue las líneas verdes).
  7. AccountManager devuelve el token de acceso a MyApp.
  8. MyApp envía una solicitud a MySite para los datos privados del usuario, incluido el token de acceso.
  9. MySite necesita verificar el usuario, usando el token de acceso. Valida el token como se describe aquí , con Google – "Google, es este símbolo válido?".
  10. Ahora, lo que quiero que suceda es que Google diga "Sí, quien te la dio es realmente ese usuario", pero lo que creo que ocurrirá realmente (basado en el borrador de OAuth2 y la documentación de Google) es que dirá "No Este token solo es válido para MyApp, y tu eres MySite. GTFO! ".

Entonces, ¿cómo debo hacer esto? Y POR FAVOR no diga "Use OpenID" o "No use OAuth2" u otras respuestas igualmente inútiles. Ah, y realmente me gustaría seguir usando la AccountManager usuario de AccountManager agradable en lugar de popup cutre WebView s

Editar

Respuesta provisional (voy a informar de nuevo si funciona!) De Nikolay es que realmente debería funcionar, y los servidores de Google no importa de dónde vino el token de acceso. Parece un poco inseguro para mí, pero voy a ver si funciona!

Actualizar

He implementado este patrón con Facebook en lugar de Google y funciona totalmente. El servidor OAuth2 no le importa de dónde viene el token de acceso. Al menos Facebook no, así que supongo que Google tampoco.

A la luz de eso es una muy mala idea almacenar tokens de acceso! Pero también no queremos tener que golpear los servidores de Facebook / Google para comprobar la autenticación de cada solicitud, ya que se ralentizará todo. Probablemente lo mejor es agregar una cookie de autenticación adicional para su sitio que distribuya cuando su token de acceso se valide, pero una manera más sencilla es simplemente tratar el token de acceso como una contraseña y almacenar un hash de la misma. Usted no necesita salar ya sea porque las fichas de acceso son muy largas. Así que los pasos anteriores se convierten en algo como:

9. MySite necesita verificar el usuario, usando el token de acceso. Primero comprueba su caché de ficheros de acceso válidos hash. Si el hash del token se encuentra allí, sabe que el usuario está autenticado. De lo contrario, verifica con Google como se describe aquí , con Google – "Google, es este símbolo válido?".

10. Si Google dice que el token de acceso no es válido, le diremos al usuario a GTFO. De lo contrario Google dice "Sí, que es un usuario válido" y luego comprobar nuestra base de datos de usuarios registrados. Si no se encuentra ese nombre de usuario de Google (o Facebook id si usa Facebook), podemos crear un nuevo usuario. A continuación, almacenar en caché el valor hash del token de acceso.

Es probable que necesite OpenID Connect, que utiliza símbolos de OAuth para la autenticación. En cuanto a AccountManager , el soporte de OAuth actual es un poco hacky, los nuevos servicios de Google Play , que se estrenará "pronto" deberían optimizar esto. Vea aquí para una demo .

Acabo de publicar una respuesta a una pregunta StackOverflow similar.

Google llama a este Hybrid Apps y explica cómo una "aplicación Android obtiene acceso sin conexión para el back-end de la Web" .

La esencia de esto es que tendrás que pasar una cadena de scope masajeada a GoogleAuthUtil.getToken para conseguir que devuelva un código de autorización (no un token OAuth2). Ese código de autorización se puede pasar de su aplicación móvil a su servidor y ser intercambiado por un token OAuth2 y un token de actualización, de acuerdo con este esquema .

El parámetro scope tiene que ser algo así:

 oauth2:server:client_id:<your_server_client_it>:api_scope:<scope_url_1> <scope_url_2> ... 

Puede utilizar el token de acceso recuperado por la aplicación móvil en cualquier otro lugar. Drive SDK tiene una introducción agradable y sencilla que pasa por el flujo en https://developers.google.com/drive/quickstart-android

Al menos con Google, el token de acceso finalmente expira. Esta es la razón por la que el android AccountManager tiene el método invalidateAuthToken – el token de acceso en caché ha caducado, y debe indicarle al AccountManager que deje de darle el antiguo y en su lugar obtener uno nuevo. Esto hace que sea un poco más seguro para almacenar en caché el token, ya que el token en sí no le da acceso eterno como ese usuario. En su lugar, cuando es válido, simplemente dice "en algún momento en el pasado reciente, este símbolo fue adquirido por una fuente de confianza".

Aquí hay un par de cosas que he encontrado útiles cuando se trabaja con fichas. El primero es el punto final de tokeninfo de Google. El símbolo en sí es sólo JSON codificado en base64. Esto significa que no está cifrado, por lo que necesita estar seguro de estar utilizando HTTPS para la comunicación. Sin embargo, también significa que usted puede examinar el símbolo y tener una mejor idea de lo que está pasando.

https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=

Si su token era "abcdef", navegaría a:

https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=abcdef

Y Google descomprimiría el token para ti. Es un objeto JSON simple que incluye un campo "expires_in" que indica el número de segundos para los cuales el token sigue siendo válido. A las 6:03 en el video de abajo puede ver el token desempaquetado:

https://developers.google.com/events/io/sessions/383266187

Ese video incluye una visión completa de OAuth2 y vale la pena ver en su totalidad si va a tratar con OAuth y fichas. El orador también analiza otras formas de fichas Oauth2, que no son fichas de acceso, que no caducan.

Otro recurso útil es el OAuth Playground. Esto le permite hacer cosas básicas como los ámbitos de solicitudes, solicitudes de maquillaje y devolver fichas. Este enlace parece funcionar de manera esporádica, y en Chrome tuve que instalar la aplicación Oauth Playground:

https://developers.google.com/oauthplayground/

Y aquí está un tutorial de Tim Bray, el orador en el video, que explica cómo usar los tokens de acceso para comunicarse con un servidor desde una aplicación de Android. Esto fue útil para mí porque empecé a entender cómo funcionan las diferentes cosas de la Consola de API de Google:

http://android-developers.blogspot.in/2013/01/verifying-back-end-calls-from-android.html

Con respecto a la respuesta real a su pregunta, yo diría que usted nunca necesita almacenar en caché el token de acceso en el servidor. Como se explica en el enlace Verificación de las llamadas finales de Android de arriba, la verificación de un token es casi siempre una llamada estática rápida, lo que significa que no hay motivo para almacenar en caché los tokens:

Las bibliotecas pueden almacenar en caché los certificados de Google y actualizarlos sólo cuando sea necesario, por lo que la verificación es (casi siempre) una llamada estática rápida.

Por último, puede utilizar el AccountManager para obtener tokens de acceso. Sin embargo, ahora Google anima el uso de la clase GoogleAuthUtil en la biblioteca de Play Services:

En pocas palabras ¿cuál es la diferencia de usar OAuth2 request getAuthToken y getToken

Aquí nota el comentario de Tim Bray, el mismo tipo una vez más de los enlaces anteriores, diciendo que están poniendo sus esfuerzos en la ruta GoogleAuthUtil . Tenga en cuenta, sin embargo, que esto significa que estaría limitado a la autenticación de Google. Creo que el AccountManager podría ser utilizado para obtener, por ejemplo, un token de Facebook en su lugar – no es el caso con GoogleAuthUtil .

Cuando tuvimos la necesidad de hacer algo similar en un servidor OAuth que no fuera de Google, guardamos las fichas en un DB en el sitio web. La aplicación entonces utilizará servicios web para solicitar el token cuando sea necesario para solicitar datos.

El usuario puede hacer el registro de OAuth en la web o en la aplicación. Compartieron el mismo token de aplicación, de modo que pudieron compartir el mismo token de acceso. Después del registro, almacenaríamos los tokens de acceso y actualización en el DB para usarlos desde cualquier aplicación que lo necesitara.

  • Oauth 2 en una aplicación para Android
  • ¿Por qué el método GoogleAuthUtil.getToken () genera dos tipos de tokens?
  • Oauth en Appengine con los servicios de Google Play
  • Cómo manejar el error redirect_uri_mismatch cuando la aplicación Android obtiene acceso sin conexión para el back-end de la Web?
  • Android y OAUTH 2.0
  • Las pestañas personalizadas de Chrome de Android / la API web de Fitbit no se redireccionarán si la aplicación ya está autorizada. (OAuth2.0)
  • Cómo implementar un proceso de token de renovación con JWT para aplicaciones de Android
  • Token de actualización de accountmanager (acceso sin conexión)
  • ¿Cómo puedo enviar un mensaje a un dispositivo usando C2DM desde un servidor que ha sido autenticado con OAuth2?
  • ¿Cómo configurar las credenciales de Google Drive en la aplicación de Android?
  • ¿Cómo evitar mostrar la pantalla de consentimiento en nuestras propias aplicaciones nativas cuando la autenticación externa?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.