【问题标题】:Getting claims in identity server using resource owner password使用资源所有者密码在身份服务器中获取声明
【发布时间】:2018-01-04 14:18:05
【问题描述】:

我正在使用身份服务器 4 进行身份验证,授权类型为“ResourceOwnerPassword”。我能够对用户进行身份验证,但无法获得与用户相关的声明。那么我怎样才能得到这些呢?

下面是我的代码

客户

Startup.cs

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

控制器

public async Task<IActionResult> Authentication(LoginViewModel model)
        {
            var disco = await DiscoveryClient.GetAsync("http://localhost:5000");

            // request token
            var tokenClient = new TokenClient(disco.TokenEndpoint, "ro.client", "secret");
            var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(model.Email, model.Password, "api1");

            if (tokenResponse.IsError)
            {
                Console.WriteLine(tokenResponse.Error);
            }
// Here I am not getting the claims, it is coming Forbidden
            var extraClaims = new UserInfoClient(disco.UserInfoEndpoint);
            var identityClaims = await extraClaims.GetAsync(tokenResponse.AccessToken);
            if (!tokenResponse.IsError)
            {
                Console.WriteLine(identityClaims.Json);
            }

            Console.WriteLine(tokenResponse.Json);
            Console.WriteLine("\n\n");
}

服务器 启动.cs

services.AddIdentityServer()
                .AddTemporarySigningCredential()
                .AddInMemoryPersistedGrants()
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApiResources())
                .AddInMemoryClients(Config.GetClients(Configuration))
                .AddAspNetIdentity<ApplicationUser>()
                .AddProfileService<IdentityProfileService>()
                .AddResourceOwnerValidator<ResourceOwnerPasswordValidator>();

Config.cs

 public static IEnumerable<Client> GetClients(IConfigurationRoot Configuration)
        {
            // client credentials client
            return new List<Client>
            {

                // resource owner password grant client
                new Client
                {
                    ClientId = "ro.client",
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,

                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    AlwaysSendClientClaims = true,
                    AlwaysIncludeUserClaimsInIdToken = true,


                    AccessTokenType = AccessTokenType.Jwt

                }

            };
        }

public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource("api1", "My API")
            };
        }

但是当我在 jwt.io 中检查我的访问令牌时,我可以看到声明但是为什么我无法进入控制器?

对此的任何帮助表示赞赏!

【问题讨论】:

    标签: c# asp.net-core asp.net-core-mvc identityserver4


    【解决方案1】:

    您可以根据您的示例调用UserInfoEndpoint,但如果您将ApiResource 定义为需要它们,您也可以获得额外的声明。

    例如,而不是像你这样定义ApiResource

    new ApiResource("api1", "My API")
    

    您可以使用扩展格式并定义在获取此范围的访问令牌时您希望拥有的 UserClaims。 例如:

    new ApiResource
    {
        Name = "api1",
        ApiSecrets = { new Secret(*some secret*) },
        UserClaims = {
            JwtClaimTypes.Email,
            JwtClaimTypes.PhoneNumber,
            JwtClaimTypes.GivenName,
            JwtClaimTypes.FamilyName,
            JwtClaimTypes.PreferredUserName
        },
        Description = "My API",
        DisplayName = "MyApi1",
        Enabled = true,
        Scopes = { new Scope("api1") }
    }
    

    然后在您自己的IProfileService 实现中,您会发现对GetProfileDataAsync 的调用具有上下文中请求的声明的列表(ProfileDataRequestContext.RequestedClaimTypes)。鉴于所要求的内容列表,您可以将任何您喜欢的声明(无论您喜欢什么)添加到您从该方法返回的 context.IssuedClaims 中。这些将成为访问令牌的一部分。

    如果您只需要通过专门调用 UserInfo 端点来获得某些声明,则您需要创建一个 IdentityResource 定义并将该范围包含在您的原始令牌请求中。 例如:

    new IdentityResource
    {
        Name = "MyIdentityScope",
        UserClaims = {
            JwtClaimTypes.EmailVerified,
            JwtClaimTypes.PhoneNumberVerified
        }
    }
    

    但您的第一个问题是遵循此处的另一个答案,因此您不会得到“禁止”作为对 UserInfo 端点的响应!

    【讨论】:

      【解决方案2】:

      尝试在调用 UserInfoEndpoint 时随请求发送令牌。试试这个:

      var userInfoClient = new UserInfoClient(doc.UserInfoEndpoint, token);
      
      var response = await userInfoClient.GetAsync();
      var claims = response.Claims;
      

      official docs

      【讨论】:

        猜你喜欢
        • 2017-10-08
        • 1970-01-01
        • 2015-09-08
        • 2018-06-15
        • 2017-12-22
        • 2019-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多