web-dev-qa-db-ja.com

IdentityServer4を使用したロールベースの承認

IdentityServer4を使用して「ロールベースの承認」を実装し、ユーザーロールに基づいてAPIへのアクセスを許可しようとしています。

たとえば、FreeUserとPaidUserの2つのロールがユーザーにあり、[Authorize(Roles = "FreeUser"))]を使用してAuthorize Attributeを介してAPIにアクセスできるようにしたいと思います。 。

私は次のソリューション構造を持っています:

  1. IdentityServer
  2. WebApi
  3. Javascriptクライアント

Javascriptクライアントを次のように登録しました。

 new Client
            {
                ClientId = "js",
                ClientName = "javascript client",
                AllowedGrantTypes = GrantTypes.Implicit,
                AllowAccessTokensViaBrowser= true,
                RedirectUris = {"http://localhost:5004/callback.html"},
                PostLogoutRedirectUris = {"http://localhost:5004/index.html"},
                AllowedCorsOrigins = {"http://localhost:5004"},

                AllowedScopes =
                {
                    StandardScopes.OpenId.Name,
                    StandardScopes.Profile.Name,
                    "api1",
                    "role",
                    StandardScopes.AllClaims.Name
                }
            }

スコープ

 return new List<Scope>
        {
            StandardScopes.OpenId,
            StandardScopes.Profile,

            new Scope
            {
                Name = "api1",
                Description = "My API"
            },
           new Scope
           {
               Enabled = true,
               Name  = "role",
               DisplayName = "Role(s)",
               Description = "roles of user",
               Type = ScopeType.Identity,
               Claims = new List<ScopeClaim>
               {
                   new ScopeClaim("role",false)
               }
           },
           StandardScopes.AllClaims
        };

ユーザー

 return new List<InMemoryUser>
        {
            new InMemoryUser
            {
                Subject = "1",
                Username = "alice",
                Password = "password",

                Claims = new List<Claim>
                {
                    new Claim("name", "Alice"),
                    new Claim("website", "https://alice.com"),
                    new Claim("role","FreeUser")
                }
            },
            new InMemoryUser
            {
                Subject = "2",
                Username = "bob",
                Password = "password",

                Claims = new List<Claim>
                {
                    new Claim("name", "Bob"),
                    new Claim("website", "https://bob.com"),
                    new Claim("role","PaidUser")
                }
            }
        };

WebApi Startup.cs

  public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();


        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
        app.UseCors("default");
        app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
        {
            Authority = "http://localhost:5000",
            ScopeName = "api1",
            //  AdditionalScopes = new List<string> { "openid","profile", "role" },
            RequireHttpsMetadata = false
        });

        app.UseMvc();
    }

Web APIコントローラー

namespace Api.Controllers
{
 [Route("[controller]")]

public class IdentityController : ControllerBase
{
    [HttpGet]
    [Authorize(Roles = "PaidUser")]
    public IActionResult Get()
    {
        return new JsonResult(from c in User.Claims select new { c.Type,    c.Value });
    }

    [Authorize(Roles = "FreeUser")]
    [HttpGet]
    [Route("getfree")]
    public IActionResult GetFreeUser()
    {
        return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
    }
}
}

Javascript Client app.jsここでは、IdentityServerを介してユーザーにログインし、APIリクエストを作成しようとしています。

var mgr = new Oidc.UserManager(config);
mgr.getUser().then(function (user) {
if (user) {
    log("User logged in", user.profile);
} else {
    log("User is not logged in.");
}
});

function login() {
  mgr.signinRedirect();
 }

function api() {
mgr.getUser().then(function (user) {
    var url = "http://localhost:5001/identity/getfree";

    var xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = function () {
        log(xhr.status, JSON.parse(xhr.responseText));
    };

    xhr.setRequestHeader("Authorization", "Bearer " + user.access_token);
    xhr.send();
  });
 }

 function logout() {
   mgr.signoutRedirect();
 }

ログインフローは正常に機能し、正常にログインでき、アクセストークンでロールを受け取ることができます。

enter image description here

ボタン(Call Api)をクリックしてAPIにリクエストを行うと、次のエラーが表示されます。 enter image description here

20
muhammad waqas

JavaScriptクライアントの構成オブジェクトを提供していない場合、次のように構成されたスコープがあると仮定します。

scope:"openid profile api1 role"

問題の主な理由は、役割の申し立てがアクセストークンに含まれていないことだと思います。

次のようにロールクレームをapi1スコープに追加して、アクセストークンに含めます。

             new Scope
                {
                    Name = "api1",
                    DisplayName = "API1 access",
                    Description = "My API",
                    Type = ScopeType.Resource,
                    IncludeAllClaimsForUser = true,
                    Claims = new List<ScopeClaim>
                    {
                        new ScopeClaim(ClaimTypes.Name),
                        new ScopeClaim(ClaimTypes.Role)
                    }
                }

問題のデバッグについては、こちらの回答をご覧ください。 asp.net IDを使用してIDサーバー4にロールを実装

完全な実用的なソリューションはこちらです。 https://github.com/weliwita/IdentityServer4.Samples/tree/4084431

11
rawel

new Claim("role","FreeUser")new Claim(ClaimTypes.Role, "FreeUser")に変更します

または、次のようなポリシーを作成します。

services.AddAuthorization(options =>
{
    options.AddPolicy("FreeUser", policy => policy.RequireClaim("role", "FreeUser"));
});

そしてそれを使用します:

Authorize[(Policy = "FreeUser")]
5
adem caglin

この投稿にサンプルを書きました

Identity Server 4:アクセストークンへのクレームの追加

クライアントWebアプリとAPIアプリの両方で[Authorize(Role = "SuperAdmin、Admin")]を使用することもできます。

1
Mohammad Karimi