web-dev-qa-db-fra.com

Méthodes pour sécuriser une demande anonyme d'API Web

J'ai un ASP.NET MVC (PAS ASP.NET Core) application de page simple avec angular js sur le front-end. 

Mon client (navigateur) communique avec le serveur via les API Web ASP.NET. Maintenant, l’application Web est sur https mais anonyme . Il n'y a pas d'authentification de connexion/utilisateur.

L'application Web se présente sous la forme d'un assistant dans lequel l'utilisateur peut aller et venir et ajouter ou mettre à jour des champs de saisie sur la page Web. Les valeurs de saisie de formulaire sont ensuite mises à jour sur le serveur via Web API. 

Je cherche un moyen desecureappeler mon API Web, en particulier les requêtes POST/PUT. En résumé, je souhaite empêcher tout utilisateur d'appeler mon API Web directement à partir de POSTMAN ou de Fiddler. L'API Web, bien qu'anonyme, ne peut être appelée qu'à partir de la session du navigateur à l'origine de la demande.

  • Quelles sont les options dois-je pour y parvenir?

  • Puis-je utiliser le jeton Anti-Forgery ici (sans authentification)? 

  • Pour ce faire, une solution consiste à ajouter un en-tête personnalisé à chaque demande et à stocker une sorte de clé de session dans l'en-tête. Ensuite, validez l’en-tête personnalisé pour chaque demande que j’ai reçue du client. Existe-t-il d'autres moyens de réaliser cette bibliothèque prête à l'emploi ou une bibliothèque éprouvée sans passer par une solution personnalisée?

  • Si je dois choisir la solution personnalisée ci-dessus, quels sont les pièges ou les problèmes potentiels dont je dois être au courant?

9
Ankit Vijay

Tout d'abord, lorsque vous supprimez la connexion et qu'il n'y a pas de mécanisme d'authentification dans votre application, il n'y a vraiment aucun moyen de sécuriser quoi que ce soit, car tout le monde peut accéder à vos API. Je pense que ce que vous voulez, c'est vous assurer que vos API ne s'appellent que depuis votre propre site web. Malheureusement, vous ne pouvez pas y parvenir complètement, car vos API Web sont http/https, et n'importe qui, de n'importe où (comme postman, fiddler, ...) peut créer une requête http et appeler votre API.

Tout ce que vous pouvez faire est de rendre plus difficile la réponse de votre API à des requêtes, comme utiliser Anti-Forgery comme vous l'avez mentionné. 

Je vous suggère également d'ajouter un cookie pour votre application et de vérifier ce cookie dans chaque demande. Dans ce cas, il est plus compliqué (voire impossible) d'appeler votre API à l'aide de Fiddler ou de Postman.

Enfin, je vous suggère d’utiliser CORS afin que les navigateurs ne permettent à votre domaine d’appeler vos API. Ainsi, personne ne peut appeler vos API dans un navigateur de domaine différent.

6
Kahbazi

Sur la base des réponses de @Arvin et des commentaires de @Evk, voici comment je compte procéder:

  • Une fois que l'utilisateur démarre la session anonymous, générez un GUID à l'aide de la méthode Guid.NewGuid() régulière et enregistrez-le dans la base de données pour identifier la demande (je le fais maintenant). Cependant, comme mentionné ici

Le GUID peut être unique mais il n'est pas sécurisé de manière cryptographique.

  • Par conséquent, au lieu d'utiliser un GUID en texte brut, cryptez-le avec l'horodatage actuel sous la forme token et ajoutez-le à l'aide de la chaîne de requête de requête.

  • Pour chaque demande d'API ultérieure, lisez la chaîne token dans la requête, déchiffrez-la et validez-la comme suit:

    • Vérifiez l'horodatage. Si la différence de temps est supérieure à la durée prédéfinie (le jeton a expiré), rejetez la demande.

    • Valider l'identifiant unique (GUID) par rapport à la base de données

  • Depuis, je n'utilise plus le texte brut GUID, l'URI ne serait pas facile à deviner. 

De plus, avec l'horodatage, l'URI est invalidé après un certain temps. En théorie, il est toujours possible d'appeler l'API via Fiddler, mais cela devrait rendre la tâche très difficile, voire impossible.

  • Par mesure de sécurité supplémentaire, je peux également ajouter un jeton anti-contrefaçon à la demande.

Selon ma compréhension, cela aide à résoudre mon problème sous-jacent et avec cette approche, il se peut que je n’aie même pas besoin d’ajouter un cookie pour sécuriser ma session anonyme.

J'adore avoir des nouvelles de vous si cette approche est bonne et comment peut-elle être améliorée.

3
Ankit Vijay

J'ai également eu une fois le besoin étrange de disposer de fonctionnalités de session sur WebAPI et de créer un middleware OWIN Session qui fait exactement ce que vous visez.

La bibliothèque s'appelle OwinSessionMiddleware et est disponible sur github et NuGet .

Utilisation

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseSessionMiddleware();

        // other middleware registrations...
        app.UseWebApi();
    }
}

Vous pouvez également transmettre certaines options à davantage de noms de cookie Tweak, ajouter un magasin de session sauvegardé à la base de données (au lieu de en mémoire), ajouter votre propre générateur d'identifiant de session (au lieu du générateur d'identifiant par défaut basé sur GUID + partie aléatoire sécurisée générée par RNGCryptoServiceProvider).

L'identifiant de session unique lui-même est stocké sous forme de cookie sécurisé et la session est automatiquement restaurée par le middleware à chaque demande.

Il y a méthodes d'extension vous pouvez appeler à l'intérieur de votre contrôleur API pour obtenir et définir les données de session:

public SomeApiController : ApiController
{
    public IHttpActionResult MyAction()
    {
        var requestCount = Request.GetSessionProperty<int>("RequestCount");

        Request.SetSessionProperty("RequestCount", ++requestCount);
    }
}
2
huysentruitw