web-dev-qa-db-fra.com

Création d'une API pour applications mobiles - Authentification et autorisation

Vue d'ensemble

Je cherche à créer une API (REST) ​​pour mon application. Le but initial/principal sera la consommation par les applications mobiles (iPhone, Android, Symbian, etc.). J'ai étudié différents mécanismes d'authentification et d'autorisation pour les API Web (en étudiant d'autres implémentations). J'ai en tête la plupart des concepts fondamentaux, mais je suis toujours à la recherche de conseils dans quelques domaines. La dernière chose que je veux faire est de réinventer la roue, mais je ne trouve aucune solution standard qui corresponde à mes critères (toutefois, mes critères peuvent être mal orientés, alors n'hésitez pas à en faire la critique également). De plus, je veux que l'API soit la même pour toutes les plates-formes/applications qui l'utilisent.

oAuth

J'avancerai et jetterai mon objection à oAuth puisque je sais que ce sera probablement la première solution proposée. Pour les applications mobiles (ou plus spécifiquement les applications non Web), cela semble tout simplement faux. de quitter l'application (d'accéder à un navigateur Web) pour l'authentification. De plus, le navigateur n'a aucun moyen (à ma connaissance) de renvoyer le rappel à l'application (surtout multiplate-forme). Je connais un couple. des applications qui le font, mais il se sent juste mal et donne une pause dans l'application UX.

Exigences

  1. L'utilisateur entre nom d'utilisateur/mot de passe dans l'application.
  2. Chaque appel d'API est identifié par l'application appelante.
  3. Les frais généraux sont réduits au minimum et l'aspect auth est intuitif pour les développeurs.
  4. Le mécanisme est sécurisé à la fois pour l'utilisateur final (leurs identifiants de connexion ne sont pas exposés) et pour le développeur (leurs identifiants d'application ne sont pas exposés).
  5. Si possible, pas besoin de https (en aucun cas une exigence stricte).

Mes réflexions actuelles sur la mise en œuvre

Un développeur externe demandera un compte API. Ils recevront un apikey et apisecret. Chaque demande nécessitera au minimum trois paramètres.

  • apikey - donné au développeur lors de l'enregistrement
  • timestamp - sert également d'identifiant unique pour chaque message pour un apike donné
  • hash - un hachage de l'horodatage + l'apisecret

L'apikey est nécessaire pour identifier l'application à l'origine de la demande. L'horodatage agit de la même manière que oauth_nonce et évite/atténue les attaques par rejeu. Le hash garantit que la demande a bien été émise par le propriétaire de l'apike donné.

Pour les demandes authentifiées (celles effectuées au nom d'un utilisateur), je ne suis toujours pas décidé à suivre un itinéraire avec access_token ou un combo de hachage nom d'utilisateur et mot de passe. Dans les deux cas, un nom d'utilisateur/mot de passe sera nécessaire à un moment donné. Ainsi, le cas échéant, un hachage de plusieurs informations (apikey, apisecret, timestamp) + le mot de passe serait utilisé. J'aimerais des commentaires sur cet aspect. Pour votre information, ils devraient commencer par hacher le mot de passe, car je ne stocke pas les mots de passe dans mon système sans hachage.

Conclusion

Pour votre information, il ne s’agit pas de demander comment construire/structurer l’API en général, mais seulement comment gérer l’authentification et l’autorisation à partir d’une application uniquement.

Pensées aléatoires/Questions bonus

Pour les API qui requièrent uniquement un apike dans la requête, comment empêchez-vous une personne autre que le propriétaire de l'apikey de pouvoir visualiser l'apikey (depuis envoyé en clair) et faites-vous des demandes excessives pour les pousser au-delà des limites d'utilisation? Peut-être que je ne fais que penser à cela, mais ne devrait-il pas y avoir quelque chose à authentifier qu'une requête a été vérifiée auprès du propriétaire de l'apikey? Dans mon cas, c’était le but de l’apisecret, il n’est jamais montré/transmis sans être haché.

En parlant de hashes, quid de md5 vs hmac-sha1? Est-ce vraiment important quand toutes les valeurs sont hachées avec des données suffisamment longues (c'est-à-dire apisecret)?

J'avais déjà envisagé d'ajouter un sel par utilisateur/ligne au hachage de mot de passe de mon utilisateur. Si je devais faire cela, comment l'application pourrait-elle être capable de créer un hachage correspondant sans connaître le sel utilisé?

185
jsuggs

La façon dont je conçois la connexion dans mes projets est la suivante:

  1. avant de se connecter, l'utilisateur demande un login_token au serveur. Celles-ci sont générées et stockées sur le serveur sur demande et ont probablement une durée de vie limitée.

  2. pour vous connecter, l'application calcule le hachage du mot de passe des utilisateurs, puis hache le mot de passe avec le login_token pour obtenir une valeur, puis renvoie le login_token et le hachage combiné.

  3. Le serveur vérifie que le login_token Est généré et le supprime de sa liste de login_token S valides. Le serveur combine ensuite le hachage stocké du mot de passe de l'utilisateur avec le login_token Et s'assure qu'il correspond au jeton combiné soumis. Si cela correspond, vous avez authentifié votre utilisateur.

Les avantages de ceci sont que vous ne stockez jamais le mot de passe de l'utilisateur sur le serveur, le mot de passe n'est jamais transmis en clair, le hachage du mot de passe est uniquement transmis en clair lors de la création du compte (bien qu'il puisse y avoir des moyens de le contourner), et il devrait l'être. les attaques sans risque de rejeu car le login_token est retiré de la base de données lors de son utilisation.

43
Michael Anderson

Cela fait beaucoup de questions dans une, je suppose que beaucoup de gens n'ont pas réussi à lire jusqu'à la fin :)

D'après mon expérience en matière d'authentification de service Web, les utilisateurs le surdéfinissent généralement et les problèmes sont identiques à ceux que vous rencontriez sur une page Web. Les options très simples possibles pourraient inclure https pour l’étape de connexion, renvoyer un jeton, nécessiter son inclusion dans les demandes futures. Vous pouvez également utiliser l'authentification de base http et simplement transmettre des éléments dans l'en-tête. Pour renforcer la sécurité, faites pivoter/expirer les jetons fréquemment, vérifiez que les demandes proviennent du même bloc IP (cela pourrait devenir compliqué à mesure que les utilisateurs mobiles se déplacent d’une cellule à l’autre), combinez-les avec une clé API ou similaire. Vous pouvez également effectuer l’étape "request key" de oauth (une personne l’a déjà suggéré dans une réponse précédente et c’est une bonne idée)) avant d’authentifier l’utilisateur et l’utiliser comme clé requise pour générer le fichier. jeton d'accès.

Une alternative que je n’ai pas encore utilisée, mais que j’ai beaucoup entendu parler d’alternative conviviale à oAuth est xAuth . Regardez-la et si vous l'utilisez, alors je serais vraiment intéressé de connaître vos impressions.

Pour le hachage, sha1 est un peu mieux, mais ne vous y attardez pas - tout ce que les périphériques peuvent facilement (et rapidement en termes de performances) implémenter convient probablement.

J'espère que ça aide, bonne chance :)

13
Lorna Mitchell

Twitter a résolu le problème d'application externe dans oAuth en prenant en charge une variante qu'ils appellent xAuth . Malheureusement, il existe déjà une pléthore d'autres modèles portant ce nom, de sorte qu'il peut être difficile de trier en dehors.

Le protocole est oAuth, sauf qu'il ignore la phase de jeton de demande et émet simplement immédiatement une paire de jetons d'accès à la réception d'un nom d'utilisateur et d'un mot de passe. (À partir de étape E ici .) Cette demande de initiale == doit être sécurisée - envoyer le nom d'utilisateur et le mot de passe en texte brut et recevoir le jeton d'accès et le jeton secret. Une fois la paire de jetons d'accès configurée, le premier échange de jetons a-t-il eu lieu via le modèle oAuth ou le modèle xAuth n'est-il pas pertinent pour le client et le serveur pour le reste de la session?). L’avantage de pouvoir utiliser l’infrastructure existante oAuth et d’avoir à peu près la même implémentation pour les applications mobiles/Web/de bureau. Le principal inconvénient est que l’application est autorisée à accéder au nom d’utilisateur et au mot de passe du client, mais il semble que vos exigences justifient cette approche.

Quoi qu'il en soit, j'aimerais partager votre intuition et celle de plusieurs autres personnes qui répondent ici: n'essayez pas de créer quelque chose de nouveau à partir de zéro. Les protocoles de sécurité peuvent être faciles à démarrer, mais ils sont toujours difficiles à bien faire. Plus ils deviennent compliqués, moins vos développeurs tiers seront en mesure de les implémenter. Votre protocole hypothétique est très similaire à o (x) Auth - api_key/api_secret, nonce, sha1 hashing - mais au lieu de pouvoir utiliser l'une des nombreuses bibliothèques existantes que vos développeurs vont devoir lancer eux-mêmes.

9
lantius

Vous recherchez donc un mécanisme d'authentification côté serveur qui gérera les aspects authentification et autorisation d'une application mobile?

En supposant que ce soit le cas, je l’approcherais comme suit (mais seulement parce que je suis un développeur Java afin qu’un type C # le fasse différemment)):

Le service d'authentification et d'autorisation RESTful

  1. Cela fonctionnera uniquement sur HTTPS pour empêcher toute écoute indiscrète.
  2. Il sera basé sur une combinaison de RESTEasy , Spring Security et CAS (pour la connexion unique). sur plusieurs applications).
  3. Il fonctionnera avec les navigateurs et les applications client Web
  4. Une interface Web de gestion des comptes permettra aux utilisateurs de modifier leurs détails et aux administrateurs (pour certaines applications) de modifier les niveaux d'autorisation.

Bibliothèque/application de sécurité côté client

  1. Pour chaque plate-forme prise en charge (par exemple Symbian, Android, iOS, etc.), créez une implémentation appropriée de la bibliothèque de sécurité dans la langue native de la plate-forme (par exemple, Java, ObjectiveC, C, etc.).
  2. La bibliothèque doit gérer la formation de la requête HTTPS à l'aide des API disponibles pour la plate-forme donnée (par exemple Java utilise URLConnection, etc.)
  3. Les utilisateurs de la bibliothèque d’authentification et d’autorisation générale (car c’est tout ce qu’il est) coderont vers une interface spécifique et ne seront pas satisfaits si elle change jamais. Assurez-vous qu’elle soit très flexible. Suivez les choix de conception existants tels que Spring Security.

Alors, maintenant que la vue à partir de 30 000 pieds est terminée, comment procédez-vous? Eh bien, ce n'est pas si difficile de créer un système d'authentification et d'autorisation basé sur les technologies répertoriées côté serveur avec un client de navigateur. En combinaison avec HTTPS, les infrastructures fourniront un processus sécurisé basé sur un jeton partagé (généralement présenté sous forme de cookie) généré par le processus d'authentification et utilisé chaque fois que l'utilisateur souhaite faire quelque chose. Ce jeton est présenté par le client au serveur chaque fois qu'une demande est effectuée.

Dans le cas de l'application mobile locale, il semble que vous recherchiez une solution qui effectue les tâches suivantes:

  1. L'application client dispose d'une liste de contrôle d'accès (ACL) définie contrôlant l'accès d'exécution aux appels de méthode. Par exemple, un utilisateur donné peut lire une collection à partir d'une méthode, mais sa liste de contrôle d'accès autorise uniquement l'accès aux objets dont le nom est Q, de sorte que certaines données de la collection sont extraites de l'intercepteur de sécurité. Dans Java c'est simple, il vous suffit d'utiliser les annotations Spring Security sur le code d'appel et d'implémenter un processus de réponse ACL approprié. Dans d'autres langues, vous êtes autonome et vous devrez probablement fournir Code de sécurité standard qui appelle dans votre bibliothèque de sécurité Si le langage prend en charge la programmation orientée aspect (AOP), utilisez-le au maximum dans cette situation.
  2. La bibliothèque de sécurité met en cache la liste complète des autorisations dans sa mémoire privée pour l'application en cours afin qu'elle ne soit pas obligée de rester connectée. Selon la durée de la session de connexion, il peut s’agir d’une opération unique qui ne se répète jamais.

Quoi que vous fassiez, n'essayez pas d'inventer votre propre protocole de sécurité , ni d'utiliser la sécurité par obscurité. Vous ne pourrez jamais écrire un meilleur algorithme pour cela que ceux qui sont actuellement disponibles et gratuits. En outre, les gens font confiance à des algorithmes bien connus. Donc, si vous dites que votre bibliothèque de sécurité fournit l'autorisation et l'authentification pour les applications mobiles locales en utilisant une combinaison de jetons SSL, HTTPS, SpringSecurity et AES, vous bénéficiez immédiatement d'une crédibilité sur le marché.

J'espère que cela vous aide et bonne chance dans votre entreprise. Si vous souhaitez plus d'informations, faites le moi savoir - j'ai écrit pas mal d'applications Web basées sur Spring Security, ACL, etc.

8
Gary Rowe

Très tard pour la fête, mais je voulais ajouter quelques points supplémentaires à prendre en compte pour les personnes intéressées par cette question. Je travaille pour une entreprise spécialisée dans les solutions de sécurité pour les API mobiles ( approov ), de sorte que tout ce domaine correspond à mes intérêts.

Pour commencer, la chose la plus importante à prendre en compte lorsque vous essayez de sécuriser une API mobile est combien cela vaut pour vous . La bonne solution pour une banque est différente de la bonne pour quelqu'un qui fait juste des choses pour le plaisir.

Dans la solution proposée, vous indiquez qu'un minimum de trois paramètres sera requis:

  • apikey - remis au développeur lors de l'enregistrement
  • timestamp - sert également d'identifiant unique pour chaque message pour un apike donné
  • hash - un hachage de l'horodatage + l'apisecret

Cela implique que pour certains appels d'API, aucun nom d'utilisateur/mot de passe n'est requis. Cela peut être utile pour les applications où vous ne souhaitez pas forcer une connexion (navigation dans les boutiques en ligne, par exemple).

Il s’agit d’un problème légèrement différent de celui de l’authentification de l’utilisateur et qui s’apparente davantage à une authentification ou à une attestation du logiciel. Il n'y a pas d'utilisateur, mais vous voulez toujours vous assurer qu'il n'y a pas d'accès malveillant à votre API. Vous utilisez donc le secret de votre API pour signer le trafic et identifier le code qui accède à l'API comme authentique. Le problème potentiel de cette solution est que vous devez alors révéler le secret à l'intérieur de chaque version de l'application. Si quelqu'un peut extraire le secret, il peut utiliser votre API, usurper l'identité de votre logiciel mais faire ce qu'il veut.

Pour contrer cette menace, vous pouvez effectuer différentes actions en fonction de la valeur des données. L'obscurcissement est un moyen simple de rendre plus difficile l'extraction du secret. Il existe des outils qui le feront pour vous, plus particulièrement pour Android, mais vous devez toujours avoir un code qui génère votre hachage et une personne suffisamment qualifiée peut toujours appeler la fonction qui fait le hachage directement.

Un autre moyen de limiter l'utilisation excessive d'une API qui ne nécessite pas de connexion consiste à limiter le trafic et éventuellement identifier et bloquer les adresses IP suspectes. La quantité d'effort à laquelle vous voulez aller dépendra en grande partie de la valeur de vos données.

Au-delà de cela, vous pouvez facilement commencer à entrer dans le domaine de mon travail quotidien. Quoi qu’il en soit, c’est un autre aspect de la sécurisation des API que je considère important et que je voulais signaler.

5
ThePragmatist