【问题标题】:implementing roles in identity server 4 with asp.net identity使用 asp.net 身份在身份服务器 4 中实现角色
【发布时间】:2017-04-07 18:49:14
【问题描述】:

我正在使用身份服务器 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(证书) .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 网络中它显示 500 内部服务器错误)。如果我从

更改 API Authorize 属性
  [Authorize(Roles = "admin")]
            public IActionResult Get()

到(无角色):

 [Authorize]
        public IActionResult Get()

它有效,我从 mvc 应用程序中的 api 获取数据。如何在此代码中应用角色。

请提出建议。

【问题讨论】:

  • 很确定你不应该同时使用AddTemporarySigningCredential()AddSigningCredential(cert)

标签: c# asp.net-identity identityserver4 asp.net-core-1.0


【解决方案1】:

首先,您需要在 OpenIdConnectOptions() 中请求“API”范围。

oidcOptions.Scope.Add("API");

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

然后您需要检查角色声明是否包含在 API 控制器可用的声明列表中(暂时不要在授权属性中应用角色过滤器。在控制器方法中放置一个调试点并展开用户属性)。检查您收到的角色声明类型(列在声明集合中)是否与 User.Identity.RoleClaimType 属性匹配

如果您拥有的角色声明类型与User.Identity.RoleClaimType 不匹配,则使用角色过滤器的授权属性将不起作用。您可以在 IdentityServerAuthenticationOptions() 中设置正确的RoleClaimType,如下所示

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

【讨论】:

  • rawel 感谢您的回复。当我在 mvc 客户端中尝试 RoleClaimType = ClaimTypes.Role 时,我看到 RoleClaimType 不可用 codevar oidcOptions = new OpenIdConnectOptions() { AuthenticationScheme = "oidc", SignInScheme = "Cookies", Authority = "localhost:5000" , RequireHttpsMetadata = false, GetClaimsFromUserInfoEndpoint = true, RoleClaimType = ClaimTypes.Role, }; code
  • 这应该被添加到 Api。到 IdentityServerAuthenticationOptions
  • 我看到控制器中的 User.Claims 属性为空,而身份中的 RoleCalimtype 具有与上面显示的相同的值。
  • 抱歉,我不知道 Claims 集合如何为空。如果声明不可用,则授权过滤器将不起作用。检查 API 中的配置。或者从 Identity Server 存储库中的一个干净的工作示例开始。
  • 它没有显示我创建的用户声明,比如我为内存用户配置的名称等。
猜你喜欢
  • 2017-12-22
  • 2020-11-17
  • 2017-07-26
  • 1970-01-01
  • 2019-09-24
  • 1970-01-01
  • 2016-09-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多