多租户 Web 应用程序上的 AWS Cognito 用户池
AWS Cognito user pools on multi-tenant web app
我们有一个 .net Core MVC Web 应用程序,将由多个客户使用。每个客户都会有一些用户。
我们打算使用 AWS Cognito 进行用户身份验证,仔细阅读后我发现每个客户一个用户池是推荐的路线之一。这对我们的用例很有效,因为客户 A 可能想要一个用户名为 "Bob" 的用户,而客户 B 可能想要另一个用户名为 "Bob".
的用户
我读过的所有内容都表明这应该是可能的,但问题是:
在 .net 核心中,我必须在启动时指定特定于特定应用程序池的一些细节:
.AddOpenIdConnect(async options =>
{
options.ResponseType = OpenIdConnectResponseType.Code;
options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
services.BuildServiceProvider().GetService<IOpenIdDiscovery>().OpenIdConfigurationUrl(),
new OpenIdConnectConfigurationRetriever(),
services.BuildServiceProvider().GetService<System.Net.Http.HttpClient>());
options.Authority = Configuration["OpenIdAuthority"];
options.ClientId = Configuration["AuthCodeClientId"];
options.ClientSecret = Configuration["AuthCodeClientSecret"];
如何让应用程序使用多用户池?
为了详细说明以上内容,我认为理想的解决方案是:
1) 我们将用户引导至其用户池的特定登录 URL。
2)登录用户被重定向到中央站点后。
3) 我们以某种方式检测他们通过哪个用户池进行身份验证,并相应地为会话设置 ClientId 和 ClientSecret。
如果我理解正确的话,关键挑战是识别与经过身份验证的用户关联的 Cognito 用户池。解决 Cognito 发布的 ID 令牌包含标识用户池的 iss 声明。
更多详情,
这周我不得不解决类似的问题。显然.NET Core 不支持开箱即用,因为在处理基于 GUI 的网站时,它可能会引发一些关于身份验证挑战的棘手问题:https://github.com/aspnet/Security/issues/1847
不过,我是在 API 服务器的上下文中解决这个问题的,因此很容易做出一些基本假设。
我最终通过实现我自己的 JwtBearerHandler
class 解决了这个问题,它与 .NET Core 大部分相同,但是根据HTTP 请求。可以在此处找到最相关的更改:https://github.com/tgittos/AmazonCognitoPrototype/blob/master/AmazonCognitoSpike/Auth/CognitoUserPoolResolver.cs
基本上,解决方案的要点是从 JwtBearerHandler
中的请求中提取一个标识符,并使用它来重新配置 [=11= 中的 Audience
和 Authority
] 基于请求传入时存储在数据库中的内容。它不会给请求增加很多开销,而且似乎工作得很好。
我链接的整个存储库是我致力于让 Cognito 身份验证与多个用户池一起工作的概念验证,因此可能值得花一些时间阅读很多内容。它非常混乱,包括 class 我不需要更换的东西。核心变化在 CognitoUserPoolResolver
、DSJwtBearerHandler
和 DSJwtBearerOptions
.
我们有一个 .net Core MVC Web 应用程序,将由多个客户使用。每个客户都会有一些用户。
我们打算使用 AWS Cognito 进行用户身份验证,仔细阅读后我发现每个客户一个用户池是推荐的路线之一。这对我们的用例很有效,因为客户 A 可能想要一个用户名为 "Bob" 的用户,而客户 B 可能想要另一个用户名为 "Bob".
的用户我读过的所有内容都表明这应该是可能的,但问题是:
在 .net 核心中,我必须在启动时指定特定于特定应用程序池的一些细节:
.AddOpenIdConnect(async options =>
{
options.ResponseType = OpenIdConnectResponseType.Code;
options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
services.BuildServiceProvider().GetService<IOpenIdDiscovery>().OpenIdConfigurationUrl(),
new OpenIdConnectConfigurationRetriever(),
services.BuildServiceProvider().GetService<System.Net.Http.HttpClient>());
options.Authority = Configuration["OpenIdAuthority"];
options.ClientId = Configuration["AuthCodeClientId"];
options.ClientSecret = Configuration["AuthCodeClientSecret"];
如何让应用程序使用多用户池?
为了详细说明以上内容,我认为理想的解决方案是:
1) 我们将用户引导至其用户池的特定登录 URL。 2)登录用户被重定向到中央站点后。 3) 我们以某种方式检测他们通过哪个用户池进行身份验证,并相应地为会话设置 ClientId 和 ClientSecret。
如果我理解正确的话,关键挑战是识别与经过身份验证的用户关联的 Cognito 用户池。解决 Cognito 发布的 ID 令牌包含标识用户池的 iss 声明。
更多详情,
这周我不得不解决类似的问题。显然.NET Core 不支持开箱即用,因为在处理基于 GUI 的网站时,它可能会引发一些关于身份验证挑战的棘手问题:https://github.com/aspnet/Security/issues/1847
不过,我是在 API 服务器的上下文中解决这个问题的,因此很容易做出一些基本假设。
我最终通过实现我自己的 JwtBearerHandler
class 解决了这个问题,它与 .NET Core 大部分相同,但是根据HTTP 请求。可以在此处找到最相关的更改:https://github.com/tgittos/AmazonCognitoPrototype/blob/master/AmazonCognitoSpike/Auth/CognitoUserPoolResolver.cs
基本上,解决方案的要点是从 JwtBearerHandler
中的请求中提取一个标识符,并使用它来重新配置 [=11= 中的 Audience
和 Authority
] 基于请求传入时存储在数据库中的内容。它不会给请求增加很多开销,而且似乎工作得很好。
我链接的整个存储库是我致力于让 Cognito 身份验证与多个用户池一起工作的概念验证,因此可能值得花一些时间阅读很多内容。它非常混乱,包括 class 我不需要更换的东西。核心变化在 CognitoUserPoolResolver
、DSJwtBearerHandler
和 DSJwtBearerOptions
.