c# - IdentityServer 使用外部提供者登录不适用于 long login_hint 或 acr_values
问题描述
在我OpenIdConnectAuthenticationOptions
我设置了OpenIdConnectAuthenticationNotifications
RedirectToIdentityProvider
它看起来像这样:
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnectRequestType.AuthenticationRequest)
{
n.ProtocolMessage.LoginHint = "LoginHint";
n.ProtocolMessage.AcrValues = "idp:CustomIdProvider";
}
return Task.FromResult(0);
}
在此示例中,我能够收到 LoginHint 并且一切正常。
现在,如果我将 设置LoginHint
为大约 1000 个字符长的内容(同样会发生AcrValues
),IdentityServer 会显示一条错误消息:
确定您正在登录的应用程序时出错。返回应用程序并重试。
并且日志显示此消息:
找不到与登录 ID 匹配的 cookie
这只发生在LoginHint
(或AcrValues
)达到一定大小时
存储 cookie 或读取 cookie 时似乎有问题,可能它们太大了
我已经尝试/配置的内容:
客户端和服务器的Web 配置(根据这个答案,所有这些值都应该足够高,我会在它工作时将它们降低到适当的值):
<system.web>
<httpRuntime targetFramework="4.6.1" maxUrlLength="109990" maxQueryStringLength="100000" maxRequestLength="256000" />
</system.web>
<!--...-->
<requestFiltering>
<requestLimits maxQueryString="100000" maxAllowedContentLength="1073741824" />
</requestFiltering>
InputLengthRestrictions中的IdentityServerOptions
(同样的值应该足够了):
InputLengthRestrictions = new InputLengthRestrictions
{
UserName = 51200,
AcrValues = 51200,
LoginHint = 51200
}
这是此问题的后续问题:向外部身份提供者发送自定义参数
编辑:
有关我的结构的更多信息:
我的客户收到一个令牌作为查询参数,它可能很长(大约 900 个字符)。
客户端现在使用以下选项重定向到 IdentityServer:app.UseOpenIdConnectAuthentication(options);
客户 Startup.cs:
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnectRequestType.AuthenticationRequest)
{
var token = n.Request.Query.Get("token");
if (token != null)
{
n.ProtocolMessage.Parameters.Add("token", token);
n.ProtocolMessage.AcrValues = "idp:CustomIdP";
}
}
return Task.FromResult(0);
}
其余的options
都很基本
在我的 IdentityServer 上,我配置了AuthenticationOptions
' IdentityProviders
-Property,正如您在我的 IdServer 配置的摘录中看到的那样,我还将 ' -Property 设置InputLengthRestrictions
为一个高值,只是为了安全起见:
IdentityServer Startup.cs:
IdentityServerOptions options = new IdentityServerOptions
{
InputLengthRestrictions = new InputLengthRestrictions
{
RedirectUri = 51200,
AcrValues = 51200,
LoginHint = 51200
},
AuthenticationOptions = new AuthenticationOptions {
CookieOptions = new IdentityServer3.Core.Configuration.CookieOptions
{
SessionStoreProvider = new SessionStoreProvider()
},
IdentityProviders = ConfigureIdentityProviders,
}
};
idsrvApp.UseIdentityServer(options);
然后我配置我的 IdentityProviders,我的 IdentityProvider 使用Clients Startup.cs中指定的参数中的 Token 这对于短令牌来说很好,一切都按原样调用。
但是,如果令牌太长,它甚至不会走那么远。我的猜测是问题的根源在于OpenIdConnectAuthenticationHandler
编辑 2
为什么这么快就达到了极限:
显然,我的令牌被两次添加到对 IdentityServer 的请求中。
由于这个原因,cookie 的限制很快就达到了。
客户 Startup.cs:
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnectRequestType.AuthenticationRequest)
{
var token = n.Request.Query.Get("token");
if (token != null)
{
n.ProtocolMessage.Parameters.Add("token", token);
n.ProtocolMessage.AcrValues = "idp:CustomIdP";
}
}
return Task.FromResult(0);
}
在这里,我从 QueryString 中获取令牌。但我在这里错过的是,n.ProtocolMessage
已经包含了包含tokenRequestUri
的as State 参数。所以令牌被发送两次到 IdentityServer。如果我从-Parameter 中删除令牌(这是正确的做法,因为我在重定向回来时不需要它)并添加它,因为它确实按预期将其发送到 IdentityServer。state
AcrValue
但问题仍然存在。
如果 Token 真的很长怎么办?
解决方案
我不能确定,但是,这听起来可能是最大 cookie 大小问题。Cookie 在大多数浏览器
中只能存储 4096 个字节,例如,如果 cookie 以 UTF-32 存储,那么 1024 个字符将占用所有空间,并且您的 cookie 将被截断。
您可能想尝试覆盖AuthenticationOptions中的CookieOptions属性之一。
在CookieOptions
类中,您可以提供IAuthenticationSessionStoreProvider。根据对该属性的评论,它可能是您正在寻找的解决方案,至少您可以调试出问题所在。
/// <summary>
/// An optional container in which to store the identity across requests.
/// When used, only a session identifier is sent
/// to the client. This can be used to mitigate potential problems
/// with very large identities.
/// </summary>
public IAuthenticationSessionStoreProvider SessionStoreProvider { get; set; }
IAuthenticationSessionStoreProvider 没有默认实现,但您可以查看它在AuthenticationSessionStoreWrapper中的使用方式
AuthenticationSessionStoreWrapper
如果您添加提供程序,它会包含在 an 中:
static IAuthenticationSessionStore GetSessionStore(IAuthenticationSessionStoreProvider provider)
{
return provider != null ? new AuthenticationSessionStoreWrapper(provider) : null;
}
推荐阅读
- r - 有人可以解释我在使用 write.csv 时收到的错误吗
- javascript - Gijgo 网格在更改事件时不刷新
- rust - 从其中使用的类型派生的 impl 块的可见性到底是什么?
- python - textacy 安装 无缘无故被杀
- php - 在 html/php 中的单独表行中显示目录中的文件名
- python - 如何在图像上添加遮罩以模糊它们的交点?
- mysql - 为什么 MySQL 从 5.7 升级到 8.0 后出现重复输入错误?
- apache-nifi - 是否可以进行 Nifi 应用程序备份和恢复?
- asp.net-core - Entity Framework Core 未加载 1 到 0 外键实体
- java - 服务层和spring事务中的验证