Je développe plusieurs services web et une poignée de clients (application web, mobile, etc.) qui s'interfaceront avec lesdits services via HTTP (s). Mon travail actuel consiste à concevoir une solution d'authentification et d'autorisation pour le produit. J'ai décidé de tirer parti des fournisseurs d'identité externes, tels que Facebook, Google, Microsoft, Twitter, etc. pour l'authentification.
J'essaie de résoudre le problème de "quand une demande arrive sur mon serveur, comment savoir qui est l'utilisateur et comment en être sûr?". Plus de questions ci-dessous également ...
Le système doit utiliser une authentification basée sur des jetons (par opposition aux cookies par exemple ou à l'authentification de base).
Je pense que c'est le bon choix pour évoluer sur plusieurs clients et serveurs tout en offrant un couplage lâche.
Sur la base de ma lecture et de ma compréhension de l'authentification basée sur des jetons, voici comment j'imagine le flux de travail. Concentrons-nous pour l'instant sur Facebook dans un navigateur Web . Mon hypothèse est que d'autres fournisseurs d'identité externes devraient avoir des capacités similaires, même si je ne l'ai pas encore confirmé.
Remarque, au moment de la rédaction, je basais ce qui suit sur la version 2.2 de connexion Facebook
J'imagine que les étapes 5 à 9 seraient répétées pour les demandes ultérieures au serveur (alors que le jeton d'accès de l'utilisateur est valide - non expiré, révoqué du côté FB, les autorisations d'application ont été modifiées, etc.)
Voici un diagramme pour vous aider à suivre les étapes. Veuillez comprendre que ce système n'est pas une application d'une seule page (SPA). Les services Web mentionnés sont des points de terminaison API servant essentiellement à renvoyer des données JSON aux clients; ils ne servent pas HTML/JS/CSS (à l'exception des serveurs clients Web).
Tout d'abord, y a-t-il des lacunes/chutes flagrantes avec l'approche décrite en fonction de ma préface et de mes exigences?
Est-ce qu'une requête sortante est envoyée à Facebook pour vérifier le jeton d'accès (étapes 6-8 ci-dessus) par requête client requise/recommandée?
Je sais à tout le moins, je dois vérifier le jeton d'accès provenant de la demande du client. Cependant, l'approche recommandée pour les vérifications ultérieures après la première m'est inconnue. S'il existe des modèles typiques, je suis intéressé à en entendre parler. Je comprends qu'ils peuvent dépendre de l'application en fonction de mes besoins; cependant, je ne sais pas encore quoi chercher. Je ferai preuve de diligence raisonnable une fois que j'aurai une idée de base.
Par exemple, des pensées possibles:
Hachez la paire jeton d'accès + userId une fois la première vérification terminée et stockez-la dans un cache distribué (accessible par tous les serveurs Web) avec une expiration égale aux jetons d'accès. À la demande ultérieure des clients, hachez la paire jeton d'accès + ID utilisateur et vérifiez son existence dans le cache. S'il est présent, la demande est autorisée. Sinon, contactez l'API graphique Facebook pour confirmer le jeton d'accès. Je suppose que cette stratégie pourrait être réalisable si j'utilise HTTPS (ce que je serai). Cependant, comment les performances se comparent-elles?
La réponse acceptée dans cette question StackOverflow recommande de créer un jeton d'accès personnalisé une fois la première vérification du jeton d'utilisateur Facebook terminée. Le jeton personnalisé serait ensuite envoyé au client pour les demandes suivantes. Je me demande cependant si cela est plus complexe que la solution ci-dessus. Cela nécessiterait la mise en œuvre de mon propre fournisseur d'identité (quelque chose que je veux éviter parce que je veux utiliser des fournisseurs d'identité externes en premier lieu…). Y a-t-il un mérite à cette suggestion?
Le champ signedRequest est-il présent sur la réponse à l'étape 3 ci-dessus (mentionné ici ), équivalent au paramètre de demande signée ici dans le flux ‘games canvas login’?
Ils semblent être suggérés comme équivalents puisque le premier est lié au second dans la documentation. Cependant, je suis surpris que la stratégie de vérification mentionnée sur la page des jeux ne soit pas mentionnée dans la "création manuelle d'un flux de connexion" page de la documentation Web.
Si la réponse à la question n ° 3 est "Oui", la même stratégie de confirmation d’identité peut-elle décoder la signature et la comparer à ce qui devrait être utilisé côté serveur?
Je me demande si cela peut être exploité au lieu de faire un appel sortant à l'API graphique debug_token (étape n ° 6 ci-dessus) pour confirmer le jeton d'accès comme recommandé ici :
Bien sûr, afin de faire la comparaison côté serveur, la partie de demande signée devrait être envoyée avec la demande au serveur (étape n ° 5 ci-dessus). En plus de la faisabilité sans sacrifier la sécurité, je me demande comment les performances se compareraient à l’émission de l’appel sortant.
Pendant que j'y suis, dans quel scénario/dans quel but, persisteriez-vous le jeton d'accès d'un utilisateur à une base de données par exemple? Je ne vois pas de scénario où j'aurais besoin de faire cela, cependant, je peux ignorer quelque chose. Je suis curieux de savoir que certains scénarios courants pourraient être de spark quelques réflexions.
Merci!
D'après ce que vous décrivez, je suggère d'utiliser un flux de connexion côté serveur comme décrit dans
de sorte que le jeton se trouve déjà sur votre serveur et n'a pas besoin d'être transmis par le client. Si vous utilisez des connexions non cryptées, cela pourrait constituer un risque pour la sécurité (par exemple, pour les attaques de l'homme du milieu).
Les étapes seraient les suivantes:
(1) Connexion des gens
Vous devez spécifier l'autorisation que vous souhaitez collecter auprès des utilisateurs dans le paramètre scope
. La demande peut être déclenchée uniquement via un lien normal:
GET https://www.facebook.com/dialog/oauth?
client_id={app-id}
&redirect_uri={redirect-uri}
&response_type=code
&scope={permission_list}
Voir
(2) Confirmez l'identité
GET https://graph.facebook.com/oauth/access_token?
client_id={app-id}
&redirect_uri={redirect-uri}
&client_secret={app-secret}
&code={code-parameter}
(3) Inspectez le jeton d'accès
Vous pouvez inspecter le jeton comme vous l'avez déjà dit dans votre question via
GET /debug_token?input_token={token-to-inspect}
&access_token={app-token-or-admin-token}
Cela ne devrait être fait que côté serveur, car sinon vous rendriez votre jeton d'accès à l'application visible pour les utilisateurs finaux (ce n'est pas une bonne idée!).
Voir
(4) Extension du jeton d'accès
Une fois que vous avez obtenu le jeton (de courte durée), vous pouvez effectuer un appel pour étendre le jeton comme décrit dans
comme suit:
GET /oauth/access_token?grant_type=fb_exchange_token
&client_id={app-id}
&client_secret={app-secret}
&fb_exchange_token={short-lived-token}
(5) Stockage des jetons d'accès
Concernant le stockage des tokens sur le serveur, FB propose de le faire:
(6) Gestion des jetons d'accès expirés
Étant donné que FB ne vous avertit pas si un jeton a expiré (et si vous n'enregistrez pas la date d'expiration et ne la comparez pas à l'horodatage actuel avant de passer un appel), il est possible que vous receviez des messages d'erreur de FB si le jeton est invalide. (après max.60 jours). Le code d'erreur sera 190
:
{
"error": {
"message": "Error validating access token: Session has expired at unix
time SOME_TIME. The current unix time is SOME_TIME.",
"type": "OAuthException",
"code": 190
}
}
Voir
Si le jeton d'accès devient invalide, la solution consiste à demander à la personne de se reconnecter, auquel cas vous pourrez à nouveau effectuer des appels API en son nom. Le flux de connexion utilisé par votre application pour les nouvelles personnes devrait déterminer la méthode à adopter.
La réponse acceptée dans cette question StackOverflow recommande de créer un jeton d'accès personnalisé une fois la première vérification du jeton d'utilisateur Facebook terminée. Le jeton personnalisé serait ensuite envoyé au client pour les demandes suivantes. Je me demande cependant si cela est plus complexe que la solution ci-dessus. Cela nécessiterait la mise en œuvre de mon propre fournisseur d'identité (quelque chose que je veux éviter parce que je veux utiliser des fournisseurs d'identité externes en premier lieu…). Y a-t-il un mérite à cette suggestion?
À mon humble avis, c'est la voie à suivre. J'utiliserais https://jwt.io/ qui vous permet d'encoder des valeurs (le userId par exemple) en utilisant une clé secrète. Ensuite, votre client attache ce jeton à chaque demande. Ainsi, vous pouvez vérifier la demande sans avoir besoin d'un tiers (vous n'avez pas non plus besoin de requêtes de base de données). La bonne chose ici est qu'il n'est pas nécessaire de stocker le jeton sur votre base de données.
Vous pouvez définir une date d'expiration sur le jeton, pour forcer le client à s'authentifier à nouveau avec le tiers quand vous le souhaitez.
(Je ne peux pas vous aider avec les 3 et 4 questions, désolé).