C# 尝试将IdentityServer4添加为具有自定义用户存储的Javascript应用程序的身份授权

C# 尝试将IdentityServer4添加为具有自定义用户存储的Javascript应用程序的身份授权,c#,asp.net,asp.net-core,identityserver4,oidc-client-js,C#,Asp.net,Asp.net Core,Identityserver4,Oidc Client Js,我按照文档使用默认的测试配置(内存中的客户端和用户)创建了一个基本的本地实现。此时,IS4初始化如下: services.AddIdentityServer() .AddDeveloperSigningCredential() .AddInMemoryIdentityResources(Config.GetIdentityResources()) .AddInMemoryApiResources(Config.GetApiResources()) .AddInMe

我按照文档使用默认的测试配置(内存中的客户端和用户)创建了一个基本的本地实现。此时,IS4初始化如下:

services.AddIdentityServer()
    .AddDeveloperSigningCredential()
    .AddInMemoryIdentityResources(Config.GetIdentityResources())
    .AddInMemoryApiResources(Config.GetApiResources())
    .AddInMemoryClients(Config.GetClients())
    .AddTestUsers(Config.GetUsers());
然后,我介绍了如何使用该库创建一个简单的Javascript应用程序。这很好,所以现在我有了一个Javascript应用程序,它允许用户通过我的IS4实例登录。按照说明,这个JS应用程序在IS4中表示为使用隐式流的客户端

我现在想将我的IS4实例与我的real users商店集成。读了几篇文章后,我似乎需要提供
IResourceOwnerPasswordValidator
IProfileService
的实现,以及其他各种实现

我已经这样做了,现在只使用一个虚拟用户存储库,它与一组虚拟内存用户一起工作,而不是一个真正的外部存储。我的IS4初始化现在如下所示:

services.AddIdentityServer()
    .AddDeveloperSigningCredential()
    .AddInMemoryIdentityResources(Config.GetIdentityResources())
    .AddInMemoryApiResources(Config.GetApiResources())
    .AddInMemoryClients(Config.GetClients());

builder.Services.AddTransient<IProfileService, CustomProfileService>();
builder.Services.AddTransient<IResourceOwnerPasswordValidator, CustomResourceOwnerPasswordValidator>();
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients());
builder.Services.AddTransient();
builder.Services.AddTransient();
现在,当我回去测试我的Javascript应用程序时,这就是它变得奇怪的地方。当尝试登录时,我会进入我的IS4登录屏幕。我输入了预期工作的凭据,但返回了无效的用户名或密码。调试我可以看到代码从未进入
CustomResourceOwnerPasswordValidator
中的
ValidateSync
方法。然而,我偶然发现,如果我输入bobalice作为用户名和密码(例如,输入bob作为用户名和密码),那么我已经通过身份验证,可以返回到我的应用程序。这没有任何意义。我确信这些用户名不是巧合,它们是IdentityServer4示例内存用户使用的两个默认用户,但是您可以看到上面我不再使用内存用户了。事实上,即使我在
Config.cs
中注释
GetUsers
方法,这仍然是正确的

我无法解释这一点,但无论如何,我想要的是能够使用我的用户商店。因此,我进一步阅读了一些建议,认为我只能对具有
GrantTypes.ResourceOwnerPassword
的客户端使用
IResourceOwnerPasswordValidator
。然而,当我在IS4中将Javascript应用程序的客户端更改为使用此授权类型时,当我尝试登录时,我看到一个未经授权的_客户端错误


所以我被卡住了。我曾认为,由于我的设置与内存中的用户一起工作,因此使用真正的用户存储不会有太多工作,但显然我缺少了一些东西。非常感谢您的指导。

您不需要将您的
ProfileService
作为依赖项注入到您的服务中

你需要像这样的东西:

services.AddIdentityServer()
            .AddProfileService<CustomProfileService>()
            //..... more code

在那里,在
LoginInputModel
中,您有需要验证的用户名、密码等,因此如果您正在编写自定义用户管理,那么最后就不需要
IProfileService

如果第二段代码真的是您的IS4启动,我无法解释为什么“Bob”和“Alice”工作是因为您尚未连接任何配置文件服务——您需要添加一个
.AddProfileService(CustomProfileService)
调用到您的
AddIdentityServer
设置序列。您的虚拟用户存储看起来像什么?另外,您不需要注册
IProfileService
进行注入,IS4不使用它,而且在编写IS4用户界面代码时,它对用户管理没有帮助。原来bob和alice在我使用的快速入门
AccountController
中被用作测试用户。如果在代码库中快速搜索“alice”,就会发现这个问题,所以我看起来很愚蠢!非常感谢。我显然是找错人了!在你的帮助下,我现在可以工作了。这也解释了为什么我的bob和alice用户在工作——他们被设置为quick start
AccountController
的测试帐户。
/// <summary>
    /// Handle postback from username/password login
    /// </summary>
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Login(LoginInputModel model)
    {
        // logic
    }