Partager via


À propos de l’autorisation dans les microservices et les applications web .NET

Conseil / Astuce

Ce contenu est un extrait du livre électronique 'Architecture des microservices .NET pour les applications .NET conteneurisées', disponible sur .NET Docs ou en tant que PDF téléchargeable gratuitement, lisible hors ligne.

Architecture de microservices .NET pour les applications .NET conteneurisées - vignette de couverture du livre électronique.

Après l’authentification, ASP.NET API web principales doivent autoriser l’accès. Ce processus permet à un service d’autoriser uniquement les utilisateurs authentifiés à accéder aux API. L’autorisation peut être effectuée en fonction des rôles des utilisateurs ou en fonction d’une stratégie personnalisée, qui peut inclure l’inspection des revendications ou d’autres heuristiques.

La restriction de l’accès à un itinéraire MVC core ASP.NET est aussi simple que l’application d’un attribut Authorize à la méthode d’action (ou à la classe du contrôleur si toutes les actions du contrôleur nécessitent une autorisation), comme illustré dans l’exemple suivant :

public class AccountController : Controller
{
    public ActionResult Login()
    {
    }

    [Authorize]
    public ActionResult Logout()
    {
    }
}

Par défaut, l’ajout d’un attribut Authorize sans paramètres limite l’accès aux utilisateurs authentifiés pour ce contrôleur ou cette action. Pour restreindre davantage la disponibilité d’une API pour des utilisateurs spécifiques, l’attribut peut être développé pour spécifier les rôles ou stratégies requis que les utilisateurs doivent satisfaire.

Implémenter l’autorisation basée sur les rôles

ASP.NET Core Identity a un concept intégré de rôles. En plus des utilisateurs, ASP.NET Core Identity stocke des informations sur les différents rôles utilisés par l’application et effectue le suivi des utilisateurs auxquels sont affectés les rôles. Ces affectations peuvent être modifiées par programmation avec le RoleManager type qui met à jour les rôles dans le stockage persistant et le UserManager type qui peut accorder ou révoquer des rôles des utilisateurs.

Si vous vous authentifiez avec des jetons JWT, le middleware d’authentification de porteur JWT d’ASP.NET Core remplira les rôles d’un utilisateur en fonction des déclarations de rôle trouvées dans le jeton. Pour limiter l’accès à une action ou un contrôleur MVC aux utilisateurs dans des rôles spécifiques, vous pouvez inclure un paramètre Rôles dans l’annotation Autoriser (attribut), comme indiqué dans le fragment de code suivant :

[Authorize(Roles = "Administrator, PowerUser")]
public class ControlPanelController : Controller
{
    public ActionResult SetTime()
    {
    }

    [Authorize(Roles = "Administrator")]
    public ActionResult ShutDown()
    {
    }
}

Dans cet exemple, seuls les utilisateurs des rôles Administrateur ou PowerUser peuvent accéder aux API dans le contrôleur ControlPanel (par exemple, l’exécution de l’action SetTime). L’API ShutDown est plus restreinte pour autoriser l’accès uniquement aux utilisateurs dans le rôle Administrateur.

Pour exiger qu’un utilisateur soit dans plusieurs rôles, vous utilisez plusieurs attributs d’autorisation, comme illustré dans l’exemple suivant :

[Authorize(Roles = "Administrator, PowerUser")]
[Authorize(Roles = "RemoteEmployee ")]
[Authorize(Policy = "CustomPolicy")]
public ActionResult API1 ()
{
}

Dans cet exemple, pour appeler API1, un utilisateur doit :

  • Appartenir au rôle Administrator ou PowerUser, et

  • appartenir au rôle RemoteEmployee, et

  • satisfaire un gestionnaire personnalisé pour l’autorisation CustomPolicy.

Implémenter une autorisation basée sur une stratégie

Les règles d’autorisation personnalisées peuvent également être écrites à l’aide de stratégies d’autorisation. Cette section fournit une vue d’ensemble. Pour plus d’informations, consultez l’atelier d’autorisation ASP.NET.

Les stratégies d’autorisation personnalisées sont enregistrées dans la méthode Startup.ConfigureServices à l’aide de la méthode service.AddAuthorization. Cette méthode accepte un délégué qui configure un argument AuthorizationOptions.

services.AddAuthorization(options =>
{
    options.AddPolicy("AdministratorsOnly", policy =>
        policy.RequireRole("Administrator"));

    options.AddPolicy("EmployeesOnly", policy =>
        policy.RequireClaim("EmployeeNumber"));

    options.AddPolicy("Over21", policy =>
        policy.Requirements.Add(new MinimumAgeRequirement(21)));
});

Comme indiqué dans l’exemple, les stratégies peuvent être associées à différents types d’exigences. Une fois que les stratégies sont inscrites, elles peuvent être appliquées à une action ou à un contrôleur en passant le nom de la stratégie en tant qu’argument De stratégie de l’attribut Authorize (par exemple [Authorize(Policy="EmployeesOnly")]) Les stratégies peuvent avoir plusieurs exigences, pas seulement une (comme illustré dans ces exemples).

Dans l’exemple précédent, le premier appel AddPolicy est simplement une autre façon d’autoriser par rôle. Si [Authorize(Policy="AdministratorsOnly")] elle est appliquée à une API, seuls les utilisateurs du rôle Administrateur pourront y accéder.

Le deuxième AddPolicy appel illustre un moyen simple d'exiger qu'une assertion particulière soit présente pour l'utilisateur. La méthode RequireClaim peut également prendre en option des valeurs attendues pour la réclamation. Si des valeurs sont spécifiées, l’exigence est remplie uniquement si l’utilisateur a à la fois une revendication du type correct et l’une des valeurs spécifiées. Si vous utilisez le middleware d’authentification du porteur JWT, toutes les propriétés JWT sont disponibles en tant que revendications utilisateur.

La stratégie la plus intéressante présentée ici se trouve dans la troisième AddPolicy méthode, car elle utilise une exigence d’autorisation personnalisée. En utilisant des exigences d’autorisation personnalisées, vous pouvez avoir beaucoup de contrôle sur la façon dont l’autorisation est effectuée. Pour que cela fonctionne, vous devez implémenter ces types :

  • Un type d'exigences qui dérive de IAuthorizationRequirement et qui contient des champs spécifiant les détails de l'exigence. Dans l'exemple, il s'agit d'un champ d'âge pour le type d'échantillon MinimumAgeRequirement.

  • Gestionnaire qui implémente AuthorizationHandler<TRequirement>, où T est le type de IAuthorizationRequirement que le gestionnaire peut satisfaire. Le gestionnaire doit implémenter la HandleRequirementAsync méthode, qui vérifie si un contexte spécifié qui contient des informations sur l’utilisateur répond à l’exigence.

Si l’utilisateur satisfait à la condition requise, un appel à context.Succeed indiquera que l’utilisateur est autorisé. S’il existe plusieurs façons pour un utilisateur de satisfaire à une exigence d’autorisation, plusieurs gestionnaires peuvent être créés.

En plus de la nécessité d’inscrire des conditions de stratégie personnalisée avec des appels AddPolicy, vous devez aussi inscrire des gestionnaires de conditions personnalisés par le biais de l’injection de dépendance (services.AddTransient<IAuthorizationHandler, MinimumAgeHandler>()).

Un exemple d’exigence et de gestionnaire d’autorisation personnalisées pour vérifier l’âge d’un utilisateur (basé sur une DateOfBirth revendication) est disponible dans la documentation d’autorisation ASP.NET Core.

Autorisation et API minimales

ASP.NET prend en charge des API minimales comme alternative aux API basées sur le contrôleur. Les stratégies d’autorisation sont la méthode recommandée pour configurer l’autorisation pour des API minimales, comme l’illustre cet exemple :

// Program.cs
builder.Services.AddAuthorizationBuilder()
  .AddPolicy("admin_greetings", policy =>
        policy
            .RequireRole("admin")
            .RequireScope("greetings_api"));

// build the app

app.MapGet("/hello", () => "Hello world!")
  .RequireAuthorization("admin_greetings");

Ressources supplémentaires