web-dev-qa-db-fra.com

Authentification avec OAuth2 pour une application * et * un site Web

Je développe un site Web qui est principalement accessible via une application, et je souhaite utiliser OAuth2 pour l'enregistrement et l'authentification des utilisateurs. Puisqu'il s'agit d'une application Android Android, je vais commencer à utiliser les éléments OAuth2 de Google, car elle fournit une interface utilisateur décente sur Android.

Google déclare que "" Vous pouvez choisir d'utiliser le système d'authentification de Google comme un moyen d'externaliser l'authentification des utilisateurs pour votre application. Cela peut supprimer le besoin de créer, de maintenir et de sécuriser un nom d'utilisateur et un magasin de mots de passe. " qui c'est ce que je veux faire. Cependant quand je passe en revue tous leurs exemples et ainsi de suite, je ne peux trouver que des informations sur la création d'un site Web ou une application authentifie un utilisateur par rapport aux services de Google.

Et en effet, lorsque je vais enregistrer mon application ("client") avec OAuth2 de Google, il existe des options pour les clients de site Web et les clients "installés" (c'est-à-dire une application mobile) mais pas les deux. Je peux créer deux clients distincts mais j'ai lu le brouillon OAuth2 et je pense qu'il y aura un problème, que je vais maintenant expliquer.

Voici comment je l'ai envisagé:

OAuth2 flow diagram

  1. L'utilisateur demande à MyApp d'accéder à ses données privées.
  2. L'application utilise la classe AccountManager d'Android pour demander un jeton d'accès pour les API de Google.
  3. Android dit à l'utilisateur "L'application" MyApp "veut accéder à vos informations de base sur Google. Est-ce correct?"
  4. L'utilisateur dit oui.
  5. AccountManager se connecte au serveur OAuth2 de Google à l'aide des informations d'identification stockées sur le téléphone et demande un jeton d'accès.
  6. Le jeton d'accès (qui suit les lignes vertes) est retourné.
  7. AccountManager renvoie le jeton d'accès à MyApp.
  8. MyApp envoie une demande à MySite pour les données privées de l'utilisateur, y compris le jeton d'accès.
  9. MySite doit vérifier l'utilisateur à l'aide du jeton d'accès. Il valide le jeton comme décrit ici , avec Google - "Google, ce jeton est-il valide?".
  10. Maintenant, ce que je veux que se produise, c'est que Google dit "Oui, celui qui vous l'a donné est bien cet utilisateur", mais ce que je pense sera en fait (basé sur le brouillon OAuth2 et la documentation de Google) est qu'il dira "Pas question! Ce jeton n'est valable que pour MyApp, et vous êtes MySite. GTFO!".

Alors, comment dois-je faire cela? Et S'IL VOUS PLAÎT ne dites pas "Utiliser OpenID" ou "N'utilisez pas OAuth2" ou d'autres réponses tout aussi inutiles. Oh, et j'aimerais vraiment continuer à utiliser l'interface utilisateur de Nice AccountManager plutôt que le popup crappy WebViews

Éditer

La réponse provisoire (je ferai rapport si cela fonctionne!) De Nikolay est que cela devrait réellement fonctionner, et les serveurs de Google ne se soucieront pas d'où vient le jeton d'accès. Cela me semble un peu précaire, mais je vais voir si cela fonctionne!

Mise à jour

J'ai implémenté ce modèle avec Facebook au lieu de Google et cela fonctionne totalement. Le serveur OAuth2 ne se soucie pas d'où vient le jeton d'accès. Au moins, Facebook ne le fait pas, donc je suppose que Google non plus.

À la lumière de cela, c'est une très très mauvaise idée de stocker des jetons d'accès! Mais nous ne voulons pas non plus avoir à frapper les serveurs de Facebook/Google pour vérifier l'authentification pour chaque demande car cela ralentira tout. La meilleure chose à faire est probablement d'ajouter un cookie d'authentification supplémentaire pour votre site que vous remettez lorsque leur jeton d'accès est validé, mais un moyen plus simple consiste simplement à traiter le jeton d'accès comme un mot de passe et à en stocker un hachage. Vous n'avez pas besoin de le saler non plus, car les jetons d'accès sont vraiment très longs. Ainsi, les étapes ci-dessus deviennent quelque chose comme:

9. MySite doit vérifier l'utilisateur à l'aide du jeton d'accès. Tout d'abord, il vérifie son cache de jetons d'accès valides hachés. Si le hachage du jeton s'y trouve, il sait que l'utilisateur est authentifié. Sinon, il vérifie avec Google comme décrit ici , avec Google - "Google, ce jeton est-il valide?".

10. Si Google déclare que le jeton d'accès n'est pas valide, nous en informons l'utilisateur à GTFO. Sinon, Google dit "Oui, c'est un utilisateur valide" et nous vérifions ensuite notre base de données d'utilisateurs enregistrés. Si ce nom d'utilisateur Google (ou identifiant Facebook si vous utilisez Facebook) n'est pas trouvé, nous pouvons créer un nouvel utilisateur. Ensuite, nous mettons en cache la valeur hachée du jeton d'accès.

63
Timmmm

Vous avez probablement besoin d'OpenID Connect, qui utilise des jetons OAuth pour l'authentification. Quant à AccountManager, le support actuel OAuth est un peu hacky, le new Google Play Services , qui devrait être publié "bientôt" devrait, espérons-le, améliorer cela. Voir ici pour une démo .

1
Nikolay Elenkov

Je viens de poster ne réponse à une question StackOverflow similaire.

Google appelle cela Applications hybrides et explique comment une "Une application Android obtient un accès hors ligne pour le back-end Web" .

L'essentiel est que vous devrez passer une chaîne scope massée dans GoogleAuthUtil.getToken afin de lui faire retourner un code d'autorisation (pas un jeton OAuth2). Ce code d'autorisation peut être transmis de votre application mobile à votre serveur et être échangé contre un jeton OAuth2 et un jeton d'actualisation, selon ce schéma .

Le paramètre scope doit ressembler à ceci:

oauth2:server:client_id:<your_server_client_it>:api_scope:<scope_url_1> <scope_url_2> ...
5
Wolfram Arnold

Vous pouvez utiliser le jeton d'accès récupéré par l'application mobile n'importe où ailleurs. Drive SDK a une introduction simple et agréable qui passe par le flux https://developers.google.com/drive/quickstart-Android

2
Burcu Dogan

Au moins avec Google, le jeton d'accès expire finalement. C'est pourquoi le Android AccountManager a la méthode invalidateAuthToken - le jeton d'accès mis en cache a expiré, et vous devez dire au AccountManager d'arrêter de vous donner l'ancien et d'en obtenir un nouveau à la place. Cela rend un peu plus sûr la mise en cache du jeton, car le jeton lui-même ne vous donne pas un accès éternel en tant qu'utilisateur. Au lieu de cela, lorsqu'il est valide, il dit simplement "à un moment donné dans le passé récent, ce jeton a été acquis par une source de confiance".

Voici quelques éléments que j'ai trouvés utiles lors de l'utilisation de jetons. Le premier est le point de terminaison tokeninfo de Google. Le jeton lui-même est simplement JSON encodé en base64. Cela signifie qu'il n'est pas chiffré, vous devez donc être sûr d'utiliser HTTPS pour la communication. Cependant, cela signifie également que vous pouvez examiner le jeton et avoir une meilleure idée de ce qui se passe.

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

Si votre jeton était "abcdef", vous accéderiez à:

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

et Google déballerait le jeton pour vous. Il s'agit d'un simple objet JSON qui comprend un champ "expires_in" vous indiquant le nombre de secondes pendant lesquelles le jeton est toujours valide. À 6h03 dans la vidéo ci-dessous, vous pouvez voir le jeton déballé:

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

Cette vidéo comprend un aperçu complet d'OAuth2 et vaut la peine d'être regardée dans son intégralité si vous avez affaire à OAuth et jetons. L'orateur discute également d'autres formes de jetons Oauth2, qui sont pas des jetons d'accès qui n'expirent pas.

Une autre ressource utile est le OAuth Playground. Cela vous permet de faire des choses de base comme les étendues de demande, inventer des demandes et récupérer des jetons. Ce lien semble fonctionner sporadiquement et sur Chrome J'ai dû installer l'application Oauth Playground:

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

Et voici un tutoriel de Tim Bray, le conférencier de la vidéo, expliquant comment utiliser des jetons d'accès pour communiquer avec un serveur à partir d'une application Android. Cela m'a été utile parce que j'ai commencé à comprendre comment les différentes choses dans la console API Google fonctionnent ensemble:

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

En ce qui concerne la réponse réelle à votre question, je dirais que vous n'avez jamais besoin de mettre en cache le jeton d'accès sur le serveur. Comme expliqué dans la vérification des appels principaux de Android ci-dessus, la vérification d'un jeton est presque toujours un appel statique rapide, ce qui signifie qu'il n'y a aucune raison de mettre en cache les jetons:

Les bibliothèques peuvent mettre en cache les certificats Google et les actualiser uniquement lorsque cela est nécessaire, de sorte que la vérification est (presque toujours) un appel statique rapide.

Enfin, vous pouvez en effet utiliser le AccountManager pour obtenir des jetons d'accès. Cependant, Google encourage désormais l'utilisation du GoogleAuthUtil classe dans la bibliothèque Play Services à la place:

En un mot, quelle est la différence entre l'utilisation de la requête OAuth2 getAuthToken et getToken

Ici, notez le commentaire de Tim Bray, le même gars encore une fois à partir des liens ci-dessus, disant qu'ils mettent leurs efforts dans la voie GoogleAuthUtil. Notez cependant que cela signifie que vous seriez limité à l'authentification Google. Je crois que le AccountManager pourrait être utilisé pour obtenir, par exemple, un jeton Facebook à la place - pas le cas avec GoogleAuthUtil.

1
user1978019

Lorsque nous avions besoin de faire quelque chose de similaire sur un serveur non google OAuth Server, nous avons conservé les jetons dans une base de données sur le site Web. L'application utilisait ensuite les services Web pour demander le jeton en cas de besoin pour demander des données.

L'utilisateur pouvait faire l'enregistrement OAuth sur le Web ou l'application. Ils partageaient le même jeton d'application, afin qu'ils puissent partager le même jeton d'accès. Après l'enregistrement, nous stockions les jetons d'accès et d'actualisation dans la base de données pour une utilisation à partir de l'application qui en avait besoin.

0
Mark S.