web-dev-qa-db-ja.com

asp.net IDを使用してIDサーバー4にロールを実装する

IDサーバー4をトークンサービスとして使用して、asp.net MVCアプリケーションに取り組んでいます。私はいくつかの安全なリソースを持つAPIも持っています。 APIのロール(承認)を実装したい。有効なロールを持つ許可されたリソースのみがAPIエンドポイントにアクセスできることを確認したい。そうでない場合は401(無許可エラー)が発生する。

これが私の設定です:

クライアント

         new Client()
            {
                ClientId = "mvcClient",
                ClientName = "MVC Client",                    
                AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,

                ClientSecrets = new List<Secret>()
                {
                    new Secret("secret".Sha256())
                },

                RequireConsent = false;

                // where to redirect to after login
                RedirectUris = { "http://localhost:5002/signin-oidc" },
                // where to redirect to after logout
                PostLogoutRedirectUris = { "http://localhost:5002" },

                AllowedScopes =
                {
                    StandardScopes.OpenId.Name,
                    StandardScopes.Profile.Name,
                    StandardScopes.OfflineAccess.Name,
                    StandardScopes.Roles.Name,
                    "API"
                }
            }

スコープ

 return new List<Scope>()
            {
                StandardScopes.OpenId, // subject id
                StandardScopes.Profile, // first name, last name
                StandardScopes.OfflineAccess,  // requesting refresh tokens for long lived API access
               StandardScopes.Roles,
                new Scope()
                {
                    Name = "API",
                    Description = "API desc",
                     Type = ScopeType.Resource,
                    Emphasize = true,
                    IncludeAllClaimsForUser = true,
                    Claims = new List<ScopeClaim>
                    {
                        new ScopeClaim(ClaimTypes.Name),      
                        new ScopeClaim(ClaimTypes.Role)
                    }
                }
            };

ユーザー

new InMemoryUser()
                {
                    Subject = "1",
                    Username = "testuser",
                    Password = "password",
                    Claims = new List<Claim>()
                    {
                        new Claim("name", "Alice"),
                        new Claim("Website", "http://alice.com"),
                         new Claim(JwtClaimTypes.Role, "admin")

                    }
                }

サーバーの起動時にこれを追加しました:

services.AddIdentityServer().AddTemporarySigningCredential().AddSigningCredential(cert).AddInMemoryClients(Config.GetClients()).AddInMemoryScopes(Config.GetScopes()).AddInMemoryUsers(Config.GetUsers())

aPIスタートアップでは、私はこれを持っています:

  app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions()
            {
                Authority = "http://localhost:5000",
                ScopeName = "NamfusAPI",
                RequireHttpsMetadata = false
            });

aPIコントローラーでは、私はこれを持っています:

 [Authorize(Roles = "admin")]
        public IActionResult Get()
        {
            return new JsonResult(from c in User.Claims select new {c.Type, c.Value });
        }

mVCクライアントの起動で、私はこれを持っています:

 JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

 app.UseCookieAuthentication(new CookieAuthenticationOptions()
            {
                AuthenticationScheme = "Cookies"
            });


            var oidcOptions = new OpenIdConnectOptions()
            {
                AuthenticationScheme = "oidc",
                SignInScheme = "Cookies",

                Authority = "http://localhost:5000",
                RequireHttpsMetadata = false,

                ClientId = "mvcClient",
                ClientSecret = "secret",
                SaveTokens = true,
                GetClaimsFromUserInfoEndpoint = true,
                ResponseType = "code id_token", // hybrid flow

            };


            oidcOptions.Scope.Clear();
            oidcOptions.Scope.Add("openid");
            oidcOptions.Scope.Add("profile");
            oidcOptions.Scope.Add("NamfusAPI");
            oidcOptions.Scope.Add("offline_access");
            oidcOptions.Scope.Add("roles");

私はこのようにAPIを呼び出そうとしています:

public async Task<IActionResult> CallApiUsingUserAccessToken()
        {
            var accessToken = await HttpContext.Authentication.GetTokenAsync("access_token");

            var client = new HttpClient();
            client.SetBearerToken(accessToken);
            var content = await client.GetStringAsync("http://localhost:5001/identity");

            ViewBag.Json = JArray.Parse(content).ToString();
            return View("json");
        } 

アクセストークンを取得しましたが、api(identity/get)が呼び出されると、302エラーForbidden(chrome networkで500内部サーバーエラーが表示されます)が発生します。APIAuthorize属性を

  [Authorize(Roles = "admin")]
            public IActionResult Get()

へ(役割なし):

 [Authorize]
        public IActionResult Get()

それは動作し、MVCアプリでAPIからデータを取得します。このコードでどのようにロールを適用できますか?.

提案してください。

11
Asif Hameed

まず、OpenIdConnectOptions()で「API」スコープをリクエストする必要があります。

oidcOptions.Scope.Add("API");

または

Scope = { "API", "offline_access",..},

次に、ロールクレームがAPIコントローラーで使用できるクレームリストに含まれているかどうかを確認する必要があります(authorize属性でロールフィルターをまだ適用しないでください。コントローラーメソッド内にデバッグポイントを配置し、Userプロパティを展開します)。受け取った役割クレームのタイプ(クレームコレクションにリストされている)がUser.Identity.RoleClaimTypeプロパティと一致するかどうかを確認します。

enter image description here

所有している役割の要求の種類がUser.Identity.RoleClaimTypeが一致しない場合、役割フィルターを使用した属性の承認は機能しません。次のように、IdentityServerAuthenticationOptions()で正しいRoleClaimTypeを設定できます

app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
        {
            Authority = "http://localhost:5000",
            ScopeName = "API",
            RoleClaimType = ClaimTypes.Role,
            RequireHttpsMetadata = false
        });
6
rawel