使用资源所有者密码

时间:2017-07-28 13:24:49

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

我使用身份服务器4进行身份验证,使用grant类型作为'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");
}

服务器 Startup.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中检查我的访问令牌时,我可以看到声明但是为什么我无法进入控制器?

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

2 个答案:

答案 0 :(得分:3)

根据您的示例,您可以拨打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端点的响应!

答案 1 :(得分:0)

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

var userInfoClient = new UserInfoClient(doc.UserInfoEndpoint, token);

var response = await userInfoClient.GetAsync();
var claims = response.Claims;

official docs