414 votes

Conception de l'authentification Facebook dans une application iOS qui accède également à un service web sécurisé.

Objectif : Permettre à un utilisateur de s'authentifier avec Facebook dans une application iOS qui nécessite l'accès à un service web protégé que j'exécute.

Hypothèses : Un système d'authentification (et d'enregistrement) natif est en place pour les utilisateurs qui choisissent de ne pas utiliser Facebook pour se connecter.

Détails :

  • Supposons que nous voulions offrir à un utilisateur la possibilité de se connecter avec Facebook sans créer un compte/crédentiel distinct pour notre système.
  • Comme nous prenons en charge notre propre mécanisme d'authentification natif (nom d'utilisateur et mot de passe), nous avons nos propres identifiants d'utilisateur et émettons un jeton d'authentification qui est utilisé pour les interactions ultérieures après la validation initiale des informations d'identification.

Je suis surpris que Facebook ne propose pas de meilleures pratiques à ce sujet dans sa documentation destinée aux développeurs. Toute la documentation existante suppose que vous intégrez l'authentification FB à un site web ou à une application mobile autonome sans service nécessitant une authentification.

Voici mes idées initiales sur la façon dont cela pourrait être conçu, mais je voudrais savoir si elles sont correctes.

  1. Le client ouvre la connexion Facebook iOS

  2. UI L'utilisateur se connecte avec ses informations d'identification Facebook et obtient un jeton d'accès.

  3. L'application iOS transmet le jeton d'accès à notre serveur.

  4. Notre serveur communique avec l'API graphique FB en utilisant un jeton d'accès pour (a) valider le jeton et (b) obtenir l'ID utilisateur FB pour ce jeton d'accès.

    Par exemple, notre serveur appellerait https://graph.facebook.com/me/?access_token=XYZ qui renvoie les informations sur le profil dans un objet JSON.

  5. En supposant qu'il est valide, notre serveur extrait l'ID utilisateur de l'objet JSON et vérifie si l'utilisateur possède déjà un compte. Si c'est le cas, nous émettons notre propre ticket d'authentification au client qui l'utilisera pour cette session. Si l'utilisateur n'a pas de compte, nous en créons un nouveau avec l'ID utilisateur de Facebook, nous lui attribuons notre propre ID utilisateur unique et nous émettons notre ticket d'authentification.

  6. Le client renvoie ensuite le ticket d'authentification lors des interactions suivantes qui nécessitent une authentification.

Cela me semble être la bonne approche, mais je ne suis pas sûr de passer à côté de quelque chose d'extrêmement basique et de prendre le mauvais chemin (compliqué).

1 votes

Comment cela a-t-il été résolu ? J'envisage de transmettre également le jeton d'accès et de créer l'utilisateur sur le serveur. Cela semble théorique, mais je demande.

0 votes

C'était ma mise en œuvre en utilisant rails et devise : stackoverflow.com/questions/7232490/

0 votes

Pourquoi ne pas transmettre l'auth_hash complet au lieu de devoir faire deux appels à l'API FB (un depuis l'appareil iOS et un depuis le serveur) ?

83voto

Dan Ray Points 14852

Je viens d'y faire face moi-même, et voici la partie qui m'a mordue :

Dans votre étape 5... Il est possible qu'un utilisateur s'inscrive chez vous pour créer un compte entièrement distinct de son identifiant Facebook, n'est-ce pas ? Puis, une autre fois, il se connecte avec Facebook..... Et vous venez de leur créer un deuxième compte et de perdre le premier.

Il doit y avoir un moyen d'être connecté à votre service web, puis de se connecter à Facebook, et de capturer l'association entre l'identifiant Facebook et le compte local.

A part ça, votre plan semble solide.

Mise à jour : Facebook a ajouté un document décrivant un tel scénario. ICI

8 votes

Oui, j'y ai pensé et vous avez raison. Nous prévoyons de fusionner les comptes s'il s'agit de la même adresse électronique, et sinon, nous créerons un autre moyen de les fusionner.

0 votes

Quelle bibliothèque de serveur utilisez-vous du côté du serveur pour effectuer la demande ?

7 votes

@TimLeung - Si j'ai bien compris, un jeton d'accès contient l'identifiant de l'application et il est impossible d'avoir un jeton d'accès SANS l'identifiant de l'application.

31voto

zoomcrypt Points 101

Utilisez https pour transmettre le jeton d'authentification à votre serveur, comme indiqué par Facebook.

Partage des jetons d'accès

Nos politiques en matière de données interdisent explicitement tout partage d'un jeton d'accès pour votre application avec toute autre application. Cependant, nous autorisons les développeurs à partager des jetons entre une implémentation native et une implémentation serveur de la même application (c'est-à-dire en utilisant le même App ID) à condition que le transfert se fasse par HTTPS.

17voto

ivant Points 2120

Le problème que je vois avec cette stratégie, c'est que quelqu'un peut vous donner un jeton d'accès obtenu pour une autre application Facebook. Pour autant que je sache, il n'y a aucun moyen de vérifier que le jeton d'accès est pour votre application, donc vous allez simplement l'utiliser.

Cela ne semble pas très dangereux, cependant. En général, les gens/applications essaient de protéger les jetons d'accès, plutôt que de les partager.

Une exploitation possible de cette situation serait que quelqu'un crée son propre site ou son application mobile, obtienne des jetons d'accès pour ses utilisateurs et tente de les authentifier en utilisant votre API. Si cela réussit (l'utilisateur a un compte Facebook sur votre site), le site malveillant pourra utiliser votre API en se faisant passer pour l'utilisateur.

C'est un peu tiré par les cheveux, mais je pense que ça pourrait marcher.

Edit : Il semble qu'il y ait un moyen de valider le jeton d'accès après tout. Voir la réponse de @Daaniel sur la question Obtenir l'identifiant de l'application à partir du jeton d'accès de l'utilisateur (ou vérifier l'application source pour un jeton) .

0 votes

Envoi de appsecret_proof devrait empêcher cela (voir ici )

0 votes

@Tony pouvez-vous expliquer comment appsecret_proof aide ici ? D'après ce que je comprends, cela sert à prouver à Facebook que le serveur connaît la clé secrète. Cependant, ivant faisait référence à une application malveillante obtenant des jetons et les envoyant ensuite à votre API. Le serveur peut vérifier l'identifiant de l'application, mais celui-ci peut être facilement usurpé par une application malveillante. Alors... comment atténuer ce problème ?

5 votes

Vous pouvez vérifier que le jeton a été généré pour votre application grâce à https://graph.facebook.com/app/?access_token=[user_access_to‌​ken] qui renvoie l'identifiant de l'application, puis en comparant les identifiants des applications

4voto

hamsterdam Points 132

Votre solution fonctionne parfaitement.

Peut-être une alternative : pourquoi ne pas simplement récupérer l'email sur le client à partir de la demande initiale du service social et l'envoyer à votre service web ? Le service web pourrait simplement stocker l'e-mail, et peut-être aussi un social_provider. Je comprends que votre service web ne sera pas en mesure de valider l'origine de l'e-mail, mais n'existe-t-il pas une relation de confiance entre votre service web et votre client ? Si c'est le cas, il semble que vous puissiez compter sur le fait que l'e-mail provienne du bon endroit. Quelqu'un pourrait-il me dire quelle est la chose évidente que j'ai manquée et qui rend l'approche basée sur le courrier électronique absurde ?

3 votes

Je pourrais facilement découvrir comment le client parle au serveur. Ensuite, je pourrais lui envoyer des e-mails jusqu'à ce que j'obtienne un résultat. Il doit toujours y avoir une forme de vérification

5 votes

Une confiance élevée et un client ? Jamais dans la même phrase, s'il vous plaît. Sauf la phrase précédente, bien sûr.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X