web-dev-qa-db-fra.com

Authentification d'utilisateur dans l'API Web ASP.NET

Ce sujet a été incroyablement déroutant pour moi. Je suis une recrue dans les applications HTTP, mais je dois développer un client iPhone qui consomme des données JSON quelque part. J'ai choisi l'API Web de MS parce que cela semblait assez facile, mais en ce qui concerne l'authentification des utilisateurs, les choses deviennent assez frustrantes.

Je suis étonné de constater que je n'ai pas réussi à trouver un exemple clair d'authentification d'un utilisateur depuis l'écran de connexion jusqu'à l'utilisation de l'attribut Authorize sur mes méthodes ApiController après plusieurs heures de recherche sur Google.

Ce n’est pas une question, mais une demande d’exemple sur la manière de procéder. J'ai regardé les pages suivantes:

Même si ceux-ci expliquent comment traiter les demandes non autorisées, ils ne montrent pas clairement quelque chose comme une LoginController ou quelque chose comme ça pour demander les informations d'identification de l'utilisateur et les valider.

Toute personne désireuse d'écrire un exemple simple et sympathique ou de me diriger dans la bonne direction, s'il vous plaît?

Merci.

147
Luis Aguilar

Je suis étonné de constater que je n'ai pas réussi à trouver un exemple clair d'authentification d'un utilisateur depuis l'écran de connexion jusqu'à l'utilisation de l'attribut Authorize sur mes méthodes ApiController après plusieurs heures de recherche sur Google.

C'est parce que vous êtes confus au sujet de ces deux concepts:

  • L'authentification est le mécanisme par lequel les systèmes peuvent identifier en toute sécurité leurs utilisateurs. Les systèmes d'authentification apportent une réponse aux questions suivantes:

    • Qui est l'utilisateur?
    • Est-ce que l'utilisateur est vraiment ce qu'il/elle se représente?
  • L'autorisation est le mécanisme par lequel un système détermine le niveau d'accès qu'un utilisateur authentifié donné devrait avoir sur des ressources sécurisées contrôlées par le système. Par exemple, un système de gestion de base de données peut être conçu de manière à permettre à certaines personnes spécifiées de récupérer des informations d’une base de données, mais pas de modifier les données stockées dans la base de données, tout en donnant à d’autres personnes la possibilité de les modifier. Les systèmes d'autorisation apportent des réponses aux questions suivantes:

    • L'utilisateur X est-il autorisé à accéder à la ressource R?
    • L'utilisateur X est-il autorisé à effectuer l'opération P?
    • L'utilisateur X est-il autorisé à exécuter l'opération P sur la ressource R?

L'attribut Authorize dans MVC est utilisé pour appliquer des règles d'accès, par exemple:

 [System.Web.Http.Authorize(Roles = "Admin, Super User")]
 public ActionResult AdministratorsOnly()
 {
     return View();
 }

La règle ci-dessus autorise uniquement les utilisateurs des rôles Admin et super utilisateur à accéder à la méthode .

Ces règles peuvent également être définies dans le fichier web.config, à l'aide de l'élément location. Exemple:

  <location path="Home/AdministratorsOnly">
    <system.web>
      <authorization>
        <allow roles="Administrators"/>
        <deny users="*"/>
      </authorization>
    </system.web>
  </location>

Cependant, avant l'exécution de ces règles d'autorisation, vous devez être authentifié auprès du site Web actuel .

Même si ceux-ci expliquent comment gérer les demandes non autorisées, ils ne montrent pas clairement quelque chose comme un LoginController ou quelque chose comme ça pour demander des informations d'identification d'utilisateur et les valider.

À partir de là, nous pourrions diviser le problème en deux:

  • Authentifier les utilisateurs lors de l'utilisation des services de l'API Web au sein de la même application Web

    Ce serait l’approche la plus simple, car vous utiliseriez la authentification en ASP.Net

    Voici un exemple simple:

    Web.config

    <authentication mode="Forms">
      <forms
        protection="All"
        slidingExpiration="true"
        loginUrl="account/login"
        cookieless="UseCookies"
        enableCrossAppRedirects="false"
        name="cookieName"
      />
    </authentication>
    

    Les utilisateurs seront redirigés vers la route account/login. Dans ce cas, vous rendrez des contrôles personnalisés pour demander les informations d'identification de l'utilisateur, puis vous définirez le cookie d'authentification à l'aide de:

        if (ModelState.IsValid)
        {
            if (Membership.ValidateUser(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                return RedirectToAction("Index", "Home");
            }
            else
            {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
        }
    
        // If we got this far, something failed, redisplay form
        return View(model);
    
  • Authentification multiplateforme

    Ce cas serait le cas où vous exposez uniquement des services d'API Web au sein de l'application Web . Par conséquent, un autre client consomme les services, le client peut être un autre Application Web ou toute application .Net (Win Forms, WPF, console, service Windows, etc.)

    Supposons, par exemple, que vous utiliserez le service de l'API Web à partir d'une autre application Web sur le même domaine de réseau (au sein d'un intranet). Dans ce cas, vous pourriez vous fier à l'authentification Windows fournie par ASP.Net.

    <authentication mode="Windows" />
    

    Si vos services sont exposés sur Internet, vous devrez alors transmettre les jetons authentifiés à chaque service API Web.

    Pour plus d'informations, prenez un butin aux articles suivants:

176
Jupaol

Si vous souhaitez vous authentifier auprès d'un nom d'utilisateur et d'un mot de passe et sans cookie d'autorisation , l'attribut MVC4 Authorize ne fonctionnera pas immédiatement. Toutefois, vous pouvez ajouter la méthode d'assistance suivante à votre contrôleur pour accepter les en-têtes d'authentification de base. Appelez-le depuis le début des méthodes de votre contrôleur.

void EnsureAuthenticated(string role)
{
    string[] parts = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(Request.Headers.Authorization.Parameter)).Split(':');
    if (parts.Length != 2 || !Membership.ValidateUser(parts[0], parts[1]))
        throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "No account with that username and password"));
    if (role != null && !Roles.IsUserInRole(parts[0], role))
        throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "An administrator account is required"));
}

Du côté client, cet assistant crée un HttpClient avec l'en-tête d'authentification en place:

static HttpClient CreateBasicAuthenticationHttpClient(string userName, string password)
{
    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(userName + ':' + password)));
    return client;
}
15
Edward Brey

Je travaille sur un projet API MVC5/Web et je devais être en mesure d'obtenir une autorisation pour les méthodes Web Api. Lorsque ma vue d'index est chargée pour la première fois, j'appelle la méthode API Web 'token' qui, à mon avis, est créée automatiquement.

Le code côté client (CoffeeScript) pour obtenir le jeton est:

getAuthenticationToken = (username, password) ->
    dataToSend = "username=" + username + "&password=" + password
    dataToSend += "&grant_type=password"
    $.post("/token", dataToSend).success saveAccessToken

En cas de succès, l’appel suivant permet d’enregistrer le jeton d’authentification localement:

saveAccessToken = (response) ->
    window.authenticationToken = response.access_token

Ensuite, si je dois faire un appel Ajax à une méthode Web API comportant la balise [Authorize], j'ajoute simplement l'en-tête suivant à mon appel Ajax:

{ "Authorization": "Bearer " + window.authenticationToken }
9
ProfNimrod