Contexte:
Il s'agit vraiment d'une question générale sur les meilleures pratiques, mais des informations sur la situation spécifique peuvent être utiles:
Nous développons une application "connectée" pour l'iPhone. Il communiquera avec l'application backend via les services REST. Afin de ne pas avoir à demander à l'utilisateur un nom d'utilisateur et un mot de passe à chaque fois qu'il lance l'application, nous exposerons un service de "connexion" qui valide son nom d'utilisateur et son mot de passe lors du lancement initial et renvoie un jeton d'authentification qui peut être utilisé pour de futures demandes de service Web pour des données réelles. Le jeton peut avoir un délai d'expiration après lequel nous lui demanderons de s'authentifier à nouveau avec son nom d'utilisateur/mot de passe.
La question:
Quelles sont les meilleures pratiques pour générer ce type de jeton à utiliser pour l'authentification?
Par exemple, nous pourrions ...
Il semble que ce soit un problème résolu.
Sur la base des commentaires des autres réponses à cette question, des recherches supplémentaires et des discussions hors ligne, voici ce que nous avons fini par faire ...
Il a été souligné assez rapidement que le modèle d'interaction ici est essentiellement exactement le même que le modèle utilisé par l'authentification par formulaire dans ASP.NET lorsqu'une case à cocher "se souvenir de moi" est cochée. Ce n'est tout simplement pas un navigateur Web qui effectue les requêtes HTTP. Notre "ticket" équivaut au cookie défini par l'authentification par formulaire. L'authentification par formulaire utilise essentiellement une approche "crypter certaines données avec une clé secrète" par défaut.
Dans notre service Web de connexion, nous utilisons ce code pour créer un ticket:
string[] userData = new string[4];
// fill the userData array with the information we need for subsequent requests
userData[0] = ...; // data we need
userData[1] = ...; // other data, etc
// create a Forms Auth ticket with the username and the user data.
FormsAuthenticationTicket formsTicket = new FormsAuthenticationTicket(
1,
username,
DateTime.Now,
DateTime.Now.AddMinutes(DefaultTimeout),
true,
string.Join(UserDataDelimiter, userData)
);
// encrypt the ticket
string encryptedTicket = FormsAuthentication.Encrypt(formsTicket);
Ensuite, nous avons un attribut de comportement d'opération pour les services WCF qui ajoute un IParameterInspector qui vérifie un ticket valide dans les en-têtes HTTP pour la demande. Les développeurs placent cet attribut de comportement d'opération sur les opérations qui nécessitent une authentification. Voici comment ce code analyse le ticket:
// get the Forms Auth ticket object back from the encrypted Ticket
FormsAuthenticationTicket formsTicket = FormsAuthentication.Decrypt(encryptedTicket);
// split the user data back apart
string[] userData = formsTicket.UserData.Split(new string[] { UserDataDelimiter }, StringSplitOptions.None);
// verify that the username in the ticket matches the username that was sent with the request
if (formsTicket.Name == expectedUsername)
{
// ticket is valid
...
}
Construire votre propre système d'authentification est toujours une "pire pratique". C'est le genre de chose qu'il vaut mieux laisser aux professionnels qui se spécialisent dans les systèmes d'authentification.
Si vous êtes déterminé à créer votre propre architecture de "ticket expirant à partir d'un service de connexion" plutôt que de réutiliser une architecture existante, c'est probablement une bonne idée de vous familiariser au moins avec les problèmes qui ont motivé la conception de systèmes similaires, comme Kerberos. . Une introduction douce est ici:
http://web.mit.edu/kerberos/dialogue.html
Ce serait également une bonne idée de jeter un œil aux failles de sécurité qui ont été trouvées dans Kerberos (et systèmes similaires) au cours des 20 dernières années et de vous assurer de ne pas les reproduire. Kerberos a été construit par des experts en sécurité et soigneusement examiné pendant des décennies, et de graves failles algorithmiques s'y trouvent encore, comme celle-ci:
http://web.mit.edu/kerberos/www/advisories/MITKRB5-SA-2003-004-krb4.txt
Il vaut mieux apprendre de ses erreurs que les vôtres.
Amazon.com utilise un jeton de message HMAC SHA-1 pour authentifier et autoriser les demandes. Ils l'utilisent pour un service commercial assez important, donc je serais susceptible de faire confiance à leurs décisions d'ingénierie. Google publie OpenSocial API qui est quelque peu similaire. Basé sur Google et Amazon.com utilisant des approches similaires et publiées ouvertement pour sécuriser les demandes Web, je pense que ce sont probablement de bonnes façons de procéder.
L'une ou l'autre des deux réponses que vous avez fournies suffira. Vous pouvez trouver des cadres là-bas qui font cela pour vous, mais la vérité est que ce n'est pas si difficile à construire. (Chaque entreprise pour laquelle j'ai travaillé a lancé la sienne.) Le choix des jetons stockés dans la base de données par rapport aux "cookies" de données chiffrées est une décision architecturale - voulez-vous effectuer une recherche de base de données sur chaque page vue, ou préférez-vous mâcher le processeur avec le déchiffrement des cookies? Dans la plupart des applications, l'utilisation de cookies cryptés offre un gain de performances à grande échelle (si cela pose problème). Sinon, c'est juste une question de goût.
Puisque vous utilisez WCF, vous avez une variété d'options si vous utilisez CFNetwork - par exemple NTLM ou Digest Authentication:
Je sais que cela ne répond pas à votre question spécifique, mais j'ai également été confronté à ce problème (iPhone - Tomcat) et j'ai décidé d'utiliser autant que possible les services d'authentification sur le serveur Web. Dans la plupart des cas, il n'y a pas de pénalité importante pour inclure les informations d'authentification avec chaque demande. Un rapide Google révèle de nombreux articles de blog sur les services WCF et RESTful (et certaines questions connexes sur StackOverflow).
J'espère que cela t'aides!
Vous devez implémenter:
quels sont exactement les workflows, d'OAuth2, que vous recherchez. Ne réinventez pas la roue.
Cela ressemble simplement à un identifiant de session avec un long délai d'expiration. Les mêmes principes utilisés pour cela dans les applications Web pourraient s'appliquer ici.
Plutôt que de coder des informations, les identifiants de session sont choisis au hasard dans un très grand espace (128 bits). Le serveur conserve un enregistrement associant l'identifiant de session à l'utilisateur et à d'autres informations souhaitées telles que le délai d'expiration. Le client présente l'identifiant de session sur un canal sécurisé à chaque demande.
La sécurité repose sur l'imprévisibilité des identifiants de session. Générez-les avec un RNG cryptographique, à partir d'un très grand espace.