尝试将 IdentityServer4 添加为具有自定义用户存储的 Javascript 应用程序的身份授权机构
Trying to add IdentityServer4 as identity authority for a Javascript application with custom user store
我已经按照 IdentityServer4 文档使用默认测试配置(使用内存中的客户端和用户)创建了一个基本的本地实现。此时IS4初始化如下:
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetUsers());
然后我 followed the instructions for creating a simple Javascript application using the oidc-connect 图书馆。这工作正常,所以现在我有一个 Javascript 应用程序,它允许用户通过我的 IS4 实例登录。此 JS 应用程序在 IS4 中表示为根据说明使用隐式流的客户端。
我现在想将我的 IS4 实例与我的真实用户存储集成。阅读了几篇文章后,我似乎需要根据 和其他各种文章为 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 登录屏幕。我输入了我希望使用的凭据,但是 无效的用户名或密码 被 return 编辑了。调试我可以看到代码从未进入 CustomResourceOwnerPasswordValidator
中的 ValidateAsync
方法。 但是,我偶然发现如果我输入 bob 或 alice 作为用户名和密码(因此,例如,输入 bob 作为用户名 和 密码)然后我通过身份验证并且可以 return 返回我的应用程序。这没有任何意义。我确信这些是 IdentityServer4 示例内存用户使用的两个默认用户的用户名并非巧合,但您可以在上面看到我不再使用内存用户。事实上,即使我从 Config.cs
.
中注释掉 GetUsers
方法,这仍然是正确的
我无法解释这一点,但无论如何我想要的是能够使用我的用户存储。所以我进一步阅读并看到建议我只能将 IResourceOwnerPasswordValidator
用于具有 GrantTypes.ResourceOwnerPassword
的客户。但是,当我在 IS4 中更改 Javascript 应用程序的客户端以使用此授权类型时,当我尝试登录时,我看到 unauthorized_client 错误。
所以我卡住了。我曾认为,由于我的设置与内存中的用户一起使用,因此使用真实的用户存储不会有太多工作,但显然我缺少一些东西。非常感谢您的指导。
您不需要将 ProfileService
作为服务的依赖项注入。
你需要这样的东西:
services.AddIdentityServer()
.AddProfileService<CustomProfileService>()
//..... more code
此外 - 您的 CustomProfileService
不需要实现 IProfileService
(该方法接受泛型)。
真正的"magic"发生在AccountController
中:
/// <summary>
/// Handle postback from username/password login
/// </summary>
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginInputModel model)
{
// logic
}
在那里,在 LoginInputModel
中你有用户名、密码等。你需要验证,所以最后没有真正需要 IProfileService
如果你正在编写你的自定义用户管理。
我已经按照 IdentityServer4 文档使用默认测试配置(使用内存中的客户端和用户)创建了一个基本的本地实现。此时IS4初始化如下:
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetUsers());
然后我 followed the instructions for creating a simple Javascript application using the oidc-connect 图书馆。这工作正常,所以现在我有一个 Javascript 应用程序,它允许用户通过我的 IS4 实例登录。此 JS 应用程序在 IS4 中表示为根据说明使用隐式流的客户端。
我现在想将我的 IS4 实例与我的真实用户存储集成。阅读了几篇文章后,我似乎需要根据 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 登录屏幕。我输入了我希望使用的凭据,但是 无效的用户名或密码 被 return 编辑了。调试我可以看到代码从未进入 CustomResourceOwnerPasswordValidator
中的 ValidateAsync
方法。 但是,我偶然发现如果我输入 bob 或 alice 作为用户名和密码(因此,例如,输入 bob 作为用户名 和 密码)然后我通过身份验证并且可以 return 返回我的应用程序。这没有任何意义。我确信这些是 IdentityServer4 示例内存用户使用的两个默认用户的用户名并非巧合,但您可以在上面看到我不再使用内存用户。事实上,即使我从 Config.cs
.
GetUsers
方法,这仍然是正确的
我无法解释这一点,但无论如何我想要的是能够使用我的用户存储。所以我进一步阅读并看到建议我只能将 IResourceOwnerPasswordValidator
用于具有 GrantTypes.ResourceOwnerPassword
的客户。但是,当我在 IS4 中更改 Javascript 应用程序的客户端以使用此授权类型时,当我尝试登录时,我看到 unauthorized_client 错误。
所以我卡住了。我曾认为,由于我的设置与内存中的用户一起使用,因此使用真实的用户存储不会有太多工作,但显然我缺少一些东西。非常感谢您的指导。
您不需要将 ProfileService
作为服务的依赖项注入。
你需要这样的东西:
services.AddIdentityServer()
.AddProfileService<CustomProfileService>()
//..... more code
此外 - 您的 CustomProfileService
不需要实现 IProfileService
(该方法接受泛型)。
真正的"magic"发生在AccountController
中:
/// <summary>
/// Handle postback from username/password login
/// </summary>
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginInputModel model)
{
// logic
}
在那里,在 LoginInputModel
中你有用户名、密码等。你需要验证,所以最后没有真正需要 IProfileService
如果你正在编写你的自定义用户管理。