我按照IdentityServer4文档使用默认测试配置(使用内存中的客户端和用户)创建了一个基本的本地实现。此时IS4初始化如下:
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetUsers());
然后,我按照说明使用oidc-connect库创建了一个简单的 Javascript 应用程序。这很好用,所以现在我有一个 Javascript 应用程序,它允许用户通过我的 IS4 实例登录。此 JS 应用程序在 IS4 中表示为按照说明使用隐式流的客户端。
我现在想将我的 IS4 实例与我的真实用户商店集成。阅读了几篇文章后,我似乎需要根据此 SO 帖子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>();
现在,当我返回并测试我的 Javascript 应用程序时,这会变得很奇怪。尝试登录时,我被带到我的 IS4 登录屏幕。我输入了我希望工作的凭据,但返回了无效的用户名或密码。调试我可以看到代码永远不会进入我的ValidateAsync
方法CustomResourceOwnerPasswordValidator
。但是,我偶然发现,如果我输入bob或alice作为用户名和密码(例如,输入bob作为用户名和密码)然后我通过身份验证并可以返回到我的应用程序。这没有任何意义。我确信这些用户名是 IdentityServer4 示例内存用户使用的两个默认用户,这绝非巧合,但您可以在上面看到我不再使用内存用户。事实上,即使我将GetUsers
方法注释掉,这仍然是正确的Config.cs
。
我无法解释这一点,但无论如何我想要的是能够使用我的用户存储。因此,我进一步阅读并看到了我只能IResourceOwnerPasswordValidator
与拥有GrantTypes.ResourceOwnerPassword
. 但是,当我在 IS4 中更改我的 Javascript 应用程序的客户端以使用此授权类型时,当我尝试登录时,我看到了未经授权的客户端错误。
所以我被困住了。我曾认为,既然我的设置与内存用户一起工作,那么使用真正的用户存储不会有太多工作,但显然我缺少一些东西。您的指导将不胜感激。