Mise à jour:
J'ai ajouté ce lien à mon autre réponse comment utiliser l'authentification JWT pour l'API Web ASP.NET ici pour toute personne intéressée par JWT.
Nous avons réussi à appliquer l'authentification HMAC à l'API Web sécurisée, et cela a bien fonctionné. L'authentification HMAC utilise une clé secrète pour chaque consommateur que le consommateur et le serveur connaissent tous les deux pour hmac hacher un message, HMAC256 doit être utilisé. La plupart des cas, le mot de passe haché du consommateur est utilisé comme clé secrète.
Le message est normalement construit à partir des données de la requête HTTP, ou même des données personnalisées qui sont ajoutées à l'en-tête HTTP, le message peut inclure:
- Horodatage: heure à laquelle la demande est envoyée (UTC ou GMT)
- Verbe HTTP: GET, POST, PUT, DELETE.
- publier des données et une chaîne de requête,
- URL
Sous le capot, l'authentification HMAC serait:
Le consommateur envoie une requête HTTP au serveur web, après avoir construit la signature (sortie du hachage hmac), le modèle de requête HTTP:
User-Agent: {agent}
Host: {host}
Timestamp: {timestamp}
Authentication: {username}:{signature}
Exemple de demande GET:
GET /webapi.hmac/api/values
User-Agent: Fiddler
Host: localhost
Timestamp: Thursday, August 02, 2012 3:30:32 PM
Authentication: cuongle:LohrhqqoDy6PhLrHAXi7dUVACyJZilQtlDzNbLqzXlw=
Le message à hacher pour obtenir la signature:
GET\n
Thursday, August 02, 2012 3:30:32 PM\n
/webapi.hmac/api/values\n
Exemple de demande POST avec chaîne de requête (la signature ci-dessous n'est pas correcte, juste un exemple)
POST /webapi.hmac/api/values?key2=value2
User-Agent: Fiddler
Host: localhost
Content-Type: application/x-www-form-urlencoded
Timestamp: Thursday, August 02, 2012 3:30:32 PM
Authentication: cuongle:LohrhqqoDy6PhLrHAXi7dUVACyJZilQtlDzNbLqzXlw=
key1=value1&key3=value3
Le message à hacher pour obtenir la signature
GET\n
Thursday, August 02, 2012 3:30:32 PM\n
/webapi.hmac/api/values\n
key1=value1&key2=value2&key3=value3
Veuillez noter que les données de formulaire et la chaîne de requête doivent être en ordre, de sorte que le code sur le serveur récupère la chaîne de requête et les données de formulaire pour générer le message correct.
Lorsque la demande HTTP arrive sur le serveur, un filtre d'action d'authentification est implémenté pour analyser la demande afin d'obtenir des informations: verbe HTTP, horodatage, uri, données de formulaire et chaîne de requête, puis basé sur ceux-ci pour créer une signature (utiliser le hachage hmac) avec le secret clé (mot de passe haché) sur le serveur.
La clé secrète est obtenue de la base de données avec le nom d'utilisateur sur la demande.
Ensuite, le code serveur compare la signature de la demande avec la signature créée; si égal, l'authentification est passée, sinon, elle a échoué.
Le code pour construire la signature:
private static string ComputeHash(string hashedPassword, string message)
{
var key = Encoding.UTF8.GetBytes(hashedPassword.ToUpper());
string hashString;
using (var hmac = new HMACSHA256(key))
{
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
hashString = Convert.ToBase64String(hash);
}
return hashString;
}
Alors, comment empêcher l'attaque de rejeu?
Ajoutez une contrainte pour l'horodatage, quelque chose comme:
servertime - X minutes|seconds <= timestamp <= servertime + X minutes|seconds
(heure du serveur: heure de la demande qui arrive au serveur)
Et, mettez en cache la signature de la requête en mémoire (utilisez MemoryCache, devrait rester dans la limite de temps). Si la prochaine demande est accompagnée de la même signature que la précédente, elle sera rejetée.
Le code de démonstration est mis comme ici:
https://github.com/cuongle/Hmac.WebApi
Je suggérerais de commencer par les solutions les plus simples en premier - peut-être qu'une simple authentification de base HTTP + HTTPS est suffisante dans votre scénario.
Si ce n'est pas le cas (par exemple, vous ne pouvez pas utiliser https ou avez besoin d'une gestion de clés plus complexe), vous pouvez jeter un œil aux solutions basées sur HMAC comme suggéré par d'autres. Un bon exemple d'une telle API serait Amazon S3 ( http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html )
J'ai écrit un article de blog sur l'authentification basée sur HMAC dans l'API Web ASP.NET. Il traite à la fois du service d'API Web et du client d'API Web et le code est disponible sur bitbucket. http://www.piotrwalat.net/hmac-authentication-in-asp-net-web-api/
Voici un article sur l'authentification de base dans l'API Web: http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-message-handlers/
N'oubliez pas que si vous allez fournir une API à des tiers, vous serez également très probablement responsable de la livraison des bibliothèques clientes. L'authentification de base a un avantage significatif ici car elle est prise en charge sur la plupart des plates-formes de programmation prêtes à l'emploi. HMAC, d'autre part, n'est pas normalisé et nécessitera une implémentation personnalisée. Celles-ci devraient être relativement simples mais nécessitent encore du travail.
PS. Il existe également une option pour utiliser les certificats HTTPS +. http://www.piotrwalat.net/client-certificate-authentication-in-asp-net-web-api-and-windows-store-apps/
la source
Avez-vous essayé DevDefined.OAuth?
Je l'ai utilisé pour sécuriser mon WebApi avec OAuth à 2 pattes. Je l'ai également testé avec succès avec des clients PHP.
Il est assez facile d'ajouter la prise en charge d'OAuth à l'aide de cette bibliothèque. Voici comment vous pouvez implémenter le fournisseur pour l'API Web ASP.NET MVC:
1) Obtenez le code source de DevDefined.OAuth: https://github.com/bittercoder/DevDefined.OAuth - la dernière version permet l'
OAuthContextBuilder
extensibilité.2) Créez la bibliothèque et référencez-la dans votre projet d'API Web.
3) Créez un générateur de contexte personnalisé pour prendre en charge la création d'un contexte à partir de
HttpRequestMessage
:4) Utilisez ce didacticiel pour créer un fournisseur OAuth: http://code.google.com/p/devdefined-tools/wiki/OAuthProvider . Dans la dernière étape (Exemple d'accès aux ressources protégées), vous pouvez utiliser ce code dans votre
AuthorizationFilterAttribute
attribut:J'ai implémenté mon propre fournisseur, donc je n'ai pas testé le code ci-dessus (sauf bien sûr celui
WebApiOAuthContextBuilder
que j'utilise dans mon fournisseur) mais cela devrait fonctionner correctement.la source
L'API Web a introduit un attribut
[Authorize]
pour assurer la sécurité. Cela peut être défini globalement (global.asx)Ou par contrôleur:
Bien sûr, votre type d'authentification peut varier et vous souhaiterez peut-être effectuer votre propre authentification, lorsque cela se produit, vous trouverez peut-être utile d'hériter de l'attribut d'autorisation et de l'étendre pour répondre à vos besoins:
Et dans votre contrôleur:
Voici un lien sur d'autres implémentations personnalisées pour les autorisations WebApi:
http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-membership-provider/
la source
AuthorizeAttribute
, car il existe deux classes différentes portant le même nom, dans des espaces de noms différents: 1. System.Web.Mvc.AuthorizeAttribute -> pour les contrôleurs MVC 2. System.Web.Http.AuthorizeAttribute -> pour WebApi.Si vous souhaitez sécuriser votre API de serveur à serveur (pas de redirection vers le site Web pour une authentification à 2 pattes). Vous pouvez consulter le protocole d'octroi des informations d'identification client OAuth2.
https://dev.twitter.com/docs/auth/application-only-auth
J'ai développé une bibliothèque qui peut vous aider à ajouter facilement ce type de support à votre WebAPI. Vous pouvez l'installer en tant que package NuGet:
https://nuget.org/packages/OAuth2ClientCredentialsGrant/1.0.0.0
La bibliothèque cible .NET Framework 4.5.
Une fois que vous avez ajouté le package à votre projet, il crée un fichier Lisez-moi à la racine de votre projet. Vous pouvez consulter ce fichier Lisezmoi pour voir comment configurer / utiliser ce package.
À votre santé!
la source
dans la continuité de la réponse de @ Cuong Le, mon approche pour empêcher l'attaque de rejeu serait
// Chiffrer l'heure Unix côté client à l'aide de la clé privée partagée (ou du mot de passe de l'utilisateur)
// Envoyez-le dans le cadre de l'en-tête de la demande au serveur (API WEB)
// Déchiffrer l'heure Unix sur le serveur (API WEB) à l'aide de la clé privée partagée (ou du mot de passe de l'utilisateur)
// Vérifier la différence de temps entre l'heure Unix du client et l'heure Unix du serveur, ne doit pas être supérieure à x sec
// si l'ID utilisateur / le mot de passe de hachage sont corrects et que l'UnixTime déchiffré est à moins de x secondes de l'heure du serveur, alors c'est une demande valide
la source