AuthorizeAttribute con roles que no funcionan al migrar de MVC a Endpoint Routing en ASP.NET Core 3.1

Nov 26 2020

Estoy intentando actualizar mi proyecto de .UseMVC (estilo de compatibilidad de asp.net core 2.2) a .UseEndpoint Routing y me redirigen a mi página fallida de autenticación para todas mis solicitudes. Tiene que ver con las Reclamaciones: si elimino la parte del rol de [Authorize (Roles = "Admin")] para simplemente [Authorize] entonces funciona. Parece que no está recogiendo las reclamaciones que se asignan al usuario.

Parece ser un problema muy similar ya que AuthorizeAttribute no funciona con Endpoint Routing en ASP.NET Core 3.1

El siguiente párrafo es un extracto de la publicación vinculada, pero modificado para reflejar mi versión del problema.

Todo funcionó bien en 2.2, pero después de migrar a 3.1 y habilitar Endpoint Routing, este controlador comenzó a rechazar solicitudes a cualquier endpoint cuando el atributo [Authorize (Roles = "Admin")] está presente. Cuando elimino la parte "Roles =" y miro User.Claims, puedo ver que tiene los reclamos / roles requeridos. Esto sucede solo si Endpoint Routing está habilitado, en caso de usar UseMvc todo funciona correctamente. ¿Qué ocurre con la autorización en el modo de enrutamiento de punto final?

Extracto 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"});
 });

Respuestas

2 akraines Nov 29 2020 at 16:00

Resulta que, dado que estábamos usando el middleware app.Use () para completar los roles del usuario desde la base de datos, era necesario llamarlo antes de UseAuthorisation para que los roles se cargaran antes de que se realizara la autorización. (Me gusta el comentario 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();