AuthorizeAttribute with Roles ne fonctionne pas lors de la migration de MVC vers Endpoint Routing dans ASP.NET Core 3.1

Nov 26 2020

J'essaie de mettre à niveau mon projet de .UseMVC (style de compatibilité asp.net core 2.2) vers .UseEndpoint Routing et je suis redirigé vers ma page d'échec de suthentification pour toutes mes demandes. Cela a à voir avec les revendications - Si je supprime la partie rôle de [Authorize (Roles = "Admin")] pour simplement [Authorize], cela fonctionne. Il semble qu'il ne récupère pas les revendications attribuées à l'utilisateur.

Cela semble être un problème très similaire à AuthorizeAttribute qui ne fonctionne pas avec le routage de point de terminaison dans ASP.NET Core 3.1

Le paragraphe suivant est un extrait de l'article lié mais modifié pour refléter ma version du problème

Tout fonctionnait bien dans la version 2.2, mais après la migration vers la version 3.1 et l'activation du routage des points de terminaison, ce contrôleur a commencé à refuser les demandes à n'importe quel point de terminaison lorsque l'attribut [Authorize (Roles = "Admin")] est présent. Lorsque je supprime la partie "Roles =" et que je regarde User.Claims, je peux voir qu'elle contient les revendications / rôles requis. Cela se produit uniquement si Endpoint Routing est activé, en cas d'utilisation de UseMvc, tout fonctionne correctement. Quel est le problème avec l'autorisation en mode de routage de point final?

Extrait de Startup.cs

 app.UseSession();
    
 app.UseRouting();
    
 app.UseAuthentication();
 app.UseAuthorization();
 app.UseResponseCompression();
 //Add the users Roles as claims to his identity so that it is picked up for authentication purposes
 app.Use((context, next) =>
 {
     var userId = context.User.Identity.Name;
     if (userId == null)
     {
         return next();
     }
    
     ...
        
     var roles = resourceDataAccess.GetRolesForUser(userId);
     if (roles != null)
     {
         var claims = roles.Select(role => new Claim(ClaimTypes.Role, role.RoleEnum.ToString())).ToList();
    
         var appIdentity = new ClaimsIdentity(claims);
         context.User.AddIdentity(appIdentity);
     }
    
     return next();
 });
 app.UseEndpoints(endpoints =>
 {
     endpoints.MapHub<AppHub>("api/apphub");
     endpoints.MapControllerRoute("default", "api/{controller=Account}/{action=SignIn}/{id?}");
     endpoints.MapControllerRoute("catch-all", "api/{*url}",
             new {controller = "Utility", action = "NotFoundPage"});
 });

Réponses

2 akraines Nov 29 2020 at 16:00

Il s'avère que puisque nous utilisions le middleware app.Use () pour remplir les rôles de l'utilisateur à partir de la base de données, il devait être appelé avant UseAuthorisation afin que les rôles soient chargés avant que l'autorisation ne soit effectuée. (Comme le commentaire de @ CamiloTerevinto)

 app.UseSession();
    
 app.UseRouting();
    
 app.UseAuthentication();
 //Add the users Roles as claims to his identity so that it is picked up for authentication purposes
 app.Use((context, next) =>
 {
   ...
 }
 //Setup the authorisation middleware to run only after we have loaded the users roles.
 app.UseAuthorization();
 app.UseResponseCompression();