【问题标题】:Net Core 3.1 API with Identity Server 4 custom password validation带有 Identity Server 4 自定义密码验证的 Net Core 3.1 API
【发布时间】:2020-09-25 03:33:18
【问题描述】:

我正在使用身份服务器构建 API,并且需要使用现有数据库。用户密码与自定义哈希密码一起存储。 我使用 FindClientByIdAsync 来验证用户和密码,但由于密码是在非标准算法中加密的,我收到 invalid_client 错误消息。如果我在执行时间(带断点)中更改未加密值的密码值,则身份验证有效。 是否可以更改 FindClientByIdAsync 的 client_secret 验证?

自定义 ClientStore 类

public class ClientStore : IClientStore
{
    private readonly IMyUserRepository myUserRepository;

    public ClientStore(IMyUserRepository myUserRepository)
    {
        this.myUserRepository = myUserRepository;
    }

    public static IEnumerable<IdentityResource> GetIdentityResources()
    {
        return new List<IdentityResource>
        {
            new IdentityResources.OpenId()
        };
    }

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

    public async Task<Client> FindClientByIdAsync(string client)
    {
        var user = await myUserRepository.GetUserByEmailAsync(client);

        if (user == null)
            return null;

        return new Client()
        {
            ClientId = client,
            AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
            ClientSecrets =
            {
                new Secret(user.Password.Sha256()) //if I change to unencrypted works, but the value in database is hashed
            },
            AllowedScopes = { "GOLACO_API", IdentityServerConstants.StandardScopes.OpenId }
        };
    }
}

Startup 类中的身份服务器配置

services.AddIdentityServer(options =>
            {
                options.Events.RaiseSuccessEvents = true;
                options.Events.RaiseFailureEvents = true;
                options.Events.RaiseErrorEvents = true;
            })
            .AddSigningCredential(GetSigningCredential()) // here I just read the private.key file
            .AddInMemoryIdentityResources(ClientStore.GetIdentityResources())
            .AddInMemoryApiResources(ClientStore.GetApiResources())
            .AddClientStore<ClientStore>();

services.AddAuthentication("Bearer")
              .AddIdentityServerAuthentication(options =>
              {
                  options.Authority = configuration["Configuration"];
                  options.ApiName = "My_API";
                  options.RequireHttpsMetadata = false;
              });

        services.AddAuthentication()
            .AddFacebook("Facebook", options =>
            {
                options.AppId = "1234";
                options.AppSecret = "1234567890";
            });

        var policy = new AuthorizationPolicyBuilder()
               .RequireAuthenticatedUser()
               .Build();

【问题讨论】:

  • 您不能为用户使用FindClientByIdAsync。用户不是客户。有关术语,请阅读documentation

标签: asp.net-core-webapi identityserver4


【解决方案1】:

您必须像 Damien 在他的blog 中显示的那样实施IResourceOwnerPasswordValidator

public class CustomResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
    private readonly IUserRepository _userRepository;

    public CustomResourceOwnerPasswordValidator(IUserRepository userRepository)
    {
        _userRepository = userRepository;
    }

    public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
    {
        if (_userRepository.ValidateCredentials(context.UserName, context.Password))
        {
            var user = _userRepository.FindByUsername(context.UserName);
            context.Result = new GrantValidationResult(user.SubjectId, OidcConstants.AuthenticationMethods.Password);
        }

        return Task.FromResult(0);
    }
}

并在启动文件中添加builder.AddResourceOwnerValidator&lt;CustomResourceOwnerPasswordValidator&gt;();

【讨论】:

    猜你喜欢
    • 2019-08-04
    • 2017-06-26
    • 1970-01-01
    • 2021-05-02
    • 1970-01-01
    • 2018-03-29
    • 1970-01-01
    • 2020-07-10
    • 1970-01-01
    相关资源
    最近更新 更多