2

私はいくつかの概念を頭に入れようとしていますが、この質問は広すぎるとは思わない - 基本的には、役割の主張をロックする権限として使用する私たちのAPIはダウンしていますが、私はaccess_tokenが大きくなりすぎていることを発見しています。OpenIdConnect access_tokenのサイズとクレームサーバー側へのアクセス

私たちはサーバー側でOpenIddictとASP.NET Identity 3を使用しています。私たちは、デフォルトのAspNetRoleClaimsテーブルを実装して、それぞれのロールに対する要求を許可として保存しました。

ここに示すように、我々は、カスタムポリシーベースのクレーム認証を使用して、当社のAPIエンドポイントをロックダウン:

Custom Policy Based Authorization

私が発見しています主な問題は、私たちの主張を含む当社のaccess_tokenは、非常に大規模になってきているということです。クレームの足跡を小さくするために、ClaimTypeとValueをデータベースで非常に小さくしようとしています。私たちは基本的なCRUDタイプのパーミッションスキームを持っているので、SPAクライアントアプリの各 "モジュール"またはスクリーンには4つのパーミッションがあります。アプリケーションに追加するモジュールが増えるほど、access_tokenでの要求が増え、Authorization Bearerヘッダーが非常に大きくなります。私は、アプリが成長するにつれてスケーラビリティがあまり高くないことが心配です。

だから、クレームがaccess_tokenは中に埋め込まれており、私は自分のエンドポイントを打ったとき、このようなカスタムポリシーをロックダウンしている...

[Authorize(Policy="MyModuleCanRead")] 
[HttpGet] 
public IEnumerable<MyViewModel> Get() 

私はその後、私のASP.NETアイデンティティーユーザーとユーザーにアクセスすることができます。AuthorizationHandlerでのクレーム

これは明らかな質問ですが、事前に申し訳ありませんが、カスタムポリシーベース認証を有効にするためには、id_tokenまたはaccess_tokenのいずれかを使用して呼び出す必要がありますハンドラ?

access_tokenからクレームを削除すると、AuthorizationHandlerコードがヒットせず、カスタムポリシーでロックされているエンドポイントにアクセスできません。

カスタムクレームポリシーを使用することはできますが、クレームが各HTTP要求に渡されずにサーバー側からフェッチされるように、認可ハンドラ内のクレームをチェックする実際のコードがあるかどうかは疑問です認証Cookieまたはデータベースから取得します。私が探していただけのものを達成したクッキーから追加役割の主張を削除する方法についてのコメントと一緒に認証ハンドラを使用して

* UPDATE *

Pintpointの答え。

これが他の人に役立つ場合は、UserClaimsPrincipalFactoryをオーバーライドして、ロールクレームがクッキーに書き込まれないようにするコードがあります。政策を主張するが、その実際のコードを持つカスタムを使用することが可能である場合、私は疑問に思って

public class AppClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, IdentityRole> 
{ 
    public AppClaimsPrincipalFactory(UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor) 
    { 
    } 
    public override async Task<ClaimsPrincipal> CreateAsync(ApplicationUser user) 
    { 
     if (user == null) 
     { 
      throw new ArgumentNullException(nameof(user)); 
     } 
     var userId = await UserManager.GetUserIdAsync(user); 
     var userName = await UserManager.GetUserNameAsync(user); 
     var id = new ClaimsIdentity(Options.Cookies.ApplicationCookieAuthenticationScheme, 
      Options.ClaimsIdentity.UserNameClaimType, 
      Options.ClaimsIdentity.RoleClaimType); 
     id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId)); 
     id.AddClaim(new Claim(Options.ClaimsIdentity.UserNameClaimType, userName)); 
     if (UserManager.SupportsUserSecurityStamp) 
     { 
      id.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType, 
       await UserManager.GetSecurityStampAsync(user))); 
     } 

     // code removed that adds the role claims 

     if (UserManager.SupportsUserClaim) 
     { 
      id.AddClaims(await UserManager.GetClaimsAsync(user)); 
     } 
     return new ClaimsPrincipal(id); 
    } 
} 

答えて

1

を(私は権限とクッキー(Sなど多くの役割を主張していた)とリクエストヘッダは、大きくなりすぎました)クレームが各HTTP要求に渡されるのではなく、認可クッキーまたはデータベースからフェッチされたサーバー側になるように、認可ハンドラ内のクレームをチェックします。

間違いなく可能です。あなたがそれを行う方法は次のとおりです。

public class Startup 
{ 
    public void ConfigureServices(IServiceCollection services) 
    { 
     services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>(); 

     services.AddAuthorization(options => 
     { 
      options.AddPolicy("Has-Edit-User-Profiles-Permission", builder => 
      { 
       builder.RequirePermission("Edit-User-Profiles"); 
      }); 
     }); 
    } 
} 

public class PermissionAuthorizationRequirement : IAuthorizationRequirement 
{ 
    public PermissionAuthorizationRequirement(string permission) 
    { 
     if (string.IsNullOrEmpty(permission)) 
     { 
      throw new ArgumentException("The permission cannot be null or empty.", nameof(permission)); 
     } 

     Permission = permission; 
    } 

    public string Permission { get; set; } 
} 

public class PermissionAuthorizationHandler : 
    AuthorizationHandler<PermissionAuthorizationRequirement> 
{ 
    private readonly UserManager<ApplicationUser> _userManager; 

    public PermissionAuthorizationHandler(UserManager<ApplicationUser> userManager) 
    { 
     if (userManager == null) 
     { 
      throw new ArgumentNullException(nameof(userManager)); 
     } 

     _userManager = userManager; 
    } 

    protected override async Task HandleRequirementAsync(
     AuthorizationHandlerContext context, 
     PermissionAuthorizationRequirement requirement) 
    { 
     if (context.User == null) 
     { 
      return; 
     } 

     var user = await _userManager.GetUserAsync(context.User); 
     if (user == null) 
     { 
      return; 
     } 

     // Use whatever API you need to ensure the user has the requested permission. 
     if (await _userManager.IsInRoleAsync(user, requirement.Permission)) 
     { 
      context.Succeed(requirement); 
     } 
    } 
} 

public static class PermissionAuthorizationExtensions 
{ 
    public static AuthorizationPolicyBuilder RequirePermission(
     this AuthorizationPolicyBuilder builder, string permission) 
    { 
     if (builder == null) 
     { 
      throw new ArgumentNullException(nameof(builder)); 
     } 

     if (string.IsNullOrEmpty(permission)) 
     { 
      throw new ArgumentException("The permission cannot be null or empty.", nameof(permission)); 
     } 

     return builder.AddRequirements(new PermissionAuthorizationRequirement(permission)); 
    } 
} 
+0

おかげさまでピンポイント - すばらしい例です。これは、多くの役割主張では大部分は機能します。私は、これらをid_tokenとaccess_tokenに格納しないようにすることができます。しかし、私はAspNetRoleClaimsテーブルを使用しているので、アイデンティティは私に「すぐに」提供します。これらの多くのクレームはID認証クッキーに保存されています。大きすぎる。 – user1750537

+0

私は、この役割のクレームがアイデンティティのクッキーに移入されるのを防ぐことができますか、おそらく一度私がPermissionAuthorizationHandlerをヒットしたら、これを直接照会する方法があるのだろうかと思います。おそらく、最も簡単な解決策は、AspNetRoleClaimsテーブルをまったく使用せず、自分自身のカスタムPermissionsテーブルを使用し、上記のようにPermissionAuthorizationHandlerからこれらをフェッチすることです。 – user1750537

+1

@ user1750537はいできます。 1つのオプションは、独自の 'IUserClaimsPrincipalFactory'を作成し、それをDIコンテナに登録することです:https://github.com/aspnet/Identity/blob/dev/src/Microsoft.AspNetCore.Identity/UserClaimsPrincipalFactory.cs。代わりに、 'CreateTicketAsync'メソッドを調整してロール要求を削除することもできます。 – Pinpoint

関連する問題