ASP.NET Core3.1でMVCからエンドポイントルーティングに移行するときにロールが機能しないAuthorizeAttribute

Nov 26 2020

プロジェクトを.UseMVC(asp.netコア2.2互換スタイル)から.UseEndpoint Routingにアップグレードしようとしていますが、すべての要求に対して、認証に失敗したページにリダイレクトされます。それはクレームと関係があります-[Authorize(Roles = "Admin")]の役割部分を単に[Authorize]に削除すると、機能します。ユーザーに割り当てられたクレームを取得していないようです。

これは、AuthorizeAttributeがASP.NET Core3.1のエンドポイントルーティングで機能しないのと非常によく似た問題のようです。

次の段落はリンクされた投稿からの抜粋ですが、私のバージョンの問題を反映するように変更されています

2.2ではすべて正常に機能しましたが、3.1に移行してエンドポイントルーティングを有効にした後、[Authorize(Roles = "Admin")]属性が存在する場合、このコントローラーはエンドポイントへのリクエストを拒否し始めました。「Roles =」の部分を削除してUser.Claimsを見ると、必要なクレーム/ロールが含まれていることがわかります。これは、エンドポイントルーティングが有効になっている場合にのみ発生し、UseMvcを使用している場合はすべてが正しく機能します。エンドポイントルーティングモードでの承認の何が問題になっていますか?

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

回答

2 akraines Nov 29 2020 at 16:00

app.Use()ミドルウェアを使用してDBからユーザーのロールを入力していたため、承認が実行される前にロールが読み込まれるように、UseAuthorisationの前に呼び出す必要がありました。(@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();