【发布时间】:2021-02-24 21:27:31
【问题描述】:
环境
我有一个特殊情况,即托管在通配符域上的单个 ASP.Core 5 Web 应用程序。
我有无数个动态子域,并且有一个单点登录 OpenID 授权负责认证和授权什么用户可以访问什么域。
例如,所有这些域都转到同一个 ASP.Core Web 应用程序,等等:
- device1.mydomain.io
- device2.mydomain.io
- device3.mydomain.io
- deviceN.mydomain.io
- anything.mydomain.io
如果 OIDC 重定向期间的返回 URL 指向您的用户不应访问的子域,则单点登录服务器将拒绝对您的登录进行签名。您要么有权访问该特定子域,要么没有。
目前的考虑
到目前为止,我们已经在网络服务器的 OpenID 循环中添加了事件处理程序,以根据在重定向到单点登录服务器之前联系我们的 URL 动态选择 OIDC 客户端 ID。
在重定向之后,如果该应用程序针对与该应用程序联系时不同的重定向 URL 签名,则该应用程序也将拒绝接受单点登录服务器签名的令牌。这是为了防止有人复制令牌、更改 URL 并尝试将相同的令牌用于用户不应访问的不同子域。
在 OpenID 重定向循环本身中不再存在任何安全问题。这里一切正常。
问题
但是现在在使用服务时,cookie签名后出现安全问题。
- 用户可以访问
domain1.mydomain.io,但不能访问domain2.mydomain.io。 - 用户登录
domain1.mydomain.io,ASP.Core 服务签署一个 cookie。 - 用户将 cookie 复制到 Postman 并使用它来联系
domain2.mydomain.io。 - 现在用户也可以访问
domain2.mydomain.io,因为 ASP.Core 服务从不检查 cookie 是为哪个域签名的。
如何让 ASP.Core cookie-authentication 中间件检查 cookie 是为哪个域签名的,如果域与我们联系的域不同,则拒绝它?
Startup.cs 代码
void AddOpenIdConnectServices(IServiceCollection services, IDataProtectionProvider dataProtectionProvider)
{
services
.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie(o =>
{
o.DataProtectionProvider = dataProtectionProvider;
o.Cookie.SameSite = SameSiteMode.None;
})
.AddOpenIdConnect("oidc", options =>
{
options.Authority = this.config.OpenId_Authority;
options.ClientId = this.config.OpenId_ClientId;
options.RequireHttpsMetadata = true;
options.SaveTokens = true;
// Ensure that the "state" sent to the SSO server is encrypted with the same secret as the other webservers use when scaled to >1.
// Without this login will fail because we're unable to decrypt the "state" at "signin-oidc" endpoint when coming back from the SSO-server.
options.DataProtectionProvider = dataProtectionProvider;
// Customize OpenID so that we can provide the SSO- server a dynamic client-id based on which hostname we were contacted on.
// We need to intercept the redirection to the SSO- server, as well as the audience/client-id validation when the JWT- token is returned from the SSO- server.
DynamicOpenIdClientHandler dynamicClientId = new DynamicOpenIdClientHandler(clientIdPrefix: options.ClientId);
options.Events.OnRedirectToIdentityProvider = dynamicClientId.OnRedirectToidentityProvider;
options.TokenValidationParameters.AudienceValidator = dynamicClientId.AudienceValidator;
options.Events.OnTokenValidated = dynamicClientId.OnTokenValidated;
});
}
类似问题
这是一个类似的问题,但是我不确定自定义 cookie 管理器是否是最好的方法,或者它是否可以解决问题。
【问题讨论】:
-
设置
CookieDomain应该可以工作,但问题是您如何为每个应用设置该信息,可能涉及动态。 -
可以通过实现自定义 Cookie 管理器来做到这一点,但我认为它只会告诉浏览器将该 cookie 用于哪个域。并且不会阻止对为不同域签名的伪造 cookie 进行身份验证。
-
你试过了吗?我的意思是 cookie 身份验证应该使用该信息进行验证,在多个单独的应用程序的情况下,您需要做的一件事是将其设置为一个相同的值,这样用户登录一个应用程序就不必登录其他(类似于 SSO)。我已经对此进行了实践练习,并且对此非常确定。
-
酷,我想我可能假设太多而没有尝试。我现在就试试。
-
不过还是很奇怪,默认情况下如果不设置
CookieDomain,则认为是与当前主机名完全匹配,所以假设登录后@987654330 @ ,那么cookie应该不能用于登录domain2.mydomain.io。dataProtectionProvider呢?该自定义数据保护提供商可能很重要。
标签: asp.net asp.net-core security cookies oauth-2.0