AuthorizeAttribute with Roles not work when migrating from MVC to Endpoint Routing in ASP.NET Core 3.1

Nov 26 2020

Próbuję uaktualnić mój projekt z .UseMVC (styl zgodny z asp.net core 2.2) do .UseEndpoint Routing i otrzymuję przekierowanie do mojej strony niepowodzenia uwierzytelniania dla wszystkich moich żądań. Ma to związek z roszczeniami - jeśli usunę część roli [Authorize (Roles = "Admin")], aby po prostu [Authorize], to działa. Wygląda na to, że nie odbiera roszczeń przypisanych użytkownikowi.

Wydaje się, że jest to bardzo podobny problem, ponieważ AuthorizeAttribute nie działa z routingiem punktów końcowych w ASP.NET Core 3.1

Poniższy akapit jest fragmentem posta, do którego prowadzi łącze, ale został zmodyfikowany w celu odzwierciedlenia mojej wersji problemu

Wszystko działało dobrze w 2.2, ale po migracji do 3.1 i włączeniu Endpoint Routing, ten kontroler zaczął odrzucać żądania do każdego punktu końcowego, gdy obecny jest atrybut [Authorize (Roles = "Admin")]. Kiedy usuwam część „Roles =” i patrzę na User.Claims, widzę, że ma ona wymagane roszczenia / role. Dzieje się tak tylko wtedy, gdy włączony jest Endpoint Routing, w przypadku korzystania z UseMvc wszystko działa poprawnie. Co jest nie tak z autoryzacją w trybie routingu punktów końcowych?

Wyciąg z 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"});
 });

Odpowiedzi

2 akraines Nov 29 2020 at 16:00

Okazuje się, że ponieważ używaliśmy oprogramowania pośredniczącego app.Use () do wypełniania ról użytkownika z bazy danych, należało je wywołać przed UseAuthorisation, aby role zostały załadowane przed wykonaniem autoryzacji. (Podobnie jak komentarz @ 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();