AuthorizeAttribute com funções não funcionando ao migrar de MVC para Endpoint Routing no ASP.NET Core 3.1
Estou tentando atualizar meu projeto de .UseMVC (asp.net core 2.2 estilo compat) para .UseEndpoint Routing e estou sendo redirecionado para minha página de falha de autenticação para todas as minhas solicitações. Tem a ver com as Reivindicações - Se eu remover a parte da função de [Autorizar (Funções = "Admin")] para simplesmente [Autorizar], então funciona. Parece que ele não está pegando as reivindicações atribuídas ao usuário.
Parece ser um problema muito semelhante, pois AuthorizeAttribute não funciona com o roteamento de endpoint no ASP.NET Core 3.1
O parágrafo a seguir é um trecho da postagem vinculada, mas foi modificado para refletir minha versão do problema
Tudo funcionou bem no 2.2, mas depois de migrar para o 3.1 e habilitar o Endpoint Routing, este controlador começou a recusar solicitações para qualquer endpoint quando o atributo [Authorize (Roles = "Admin")] estava presente. Quando removo a parte "Roles =" e vejo User.Claims, posso ver que ele tem as declarações / funções necessárias. Isso acontece apenas se o Endpoint Routing estiver habilitado, no caso de usar UseMvc tudo funciona corretamente. O que há de errado com a autorização no modo Endpoint Routing?
Trecho 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"});
});
Respostas
Acontece que, como estávamos usando o middleware app.Use () para preencher as funções do usuário do banco de dados, ele precisava ser chamado antes de UseAuthorisation para que as funções fossem carregadas antes que a autorização fosse realizada. (Como o comentário 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();