Phr*_*ank 5 c# openid asp.net-core
我有一个使用IdentityServer4的自定义 Open Id Connect 服务器。此 SSO 服务器具有用于非标准 Open Id Connect 操作的自定义端点。
为了使用这个操作,我需要在客户端应用程序的请求中创建一个状态参数。客户端应用程序是带有 blazor 服务器端的 dotnet core 3.0 预览应用程序。
我正在使用以下内容注册 SSO 提供程序:
services.AddAuthentication(options => {
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "oidc";
})
.AddCookie()
.AddOpenIdConnect("oidc", options => {
options.ClientId = oidcClientId;
options.ClientSecret = "secret";
options.Authority = "https://test.org";
options.ResponseType = "code id_token";
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("extra");
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.RequireHttpsMetadata = false;
});
Run Code Online (Sandbox Code Playgroud)
基本登录/注销流程按预期工作,没有任何问题。
我为使用自定义 SSO 功能而生成的自定义链接如下所示(razor):
<a href=@($"https://test.org/custom/change-organization/{organization.OrganizationCode}?client_id=local-data-manager&redirect_uri=http://localhost:5000/signin-oidc&response_type=code id_token&scope=openid custom profile&nonce={GenerateNonce()}&state={GenerateState()}")>@organization.Name</a>
Run Code Online (Sandbox Code Playgroud)
使用定义的方法:
private string GenerateNonce()
{
string nonce = Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString() + Guid.NewGuid().ToString()));
return DateTime.UtcNow.Ticks.ToString(CultureInfo.InvariantCulture) + "." + nonce;
}
private string GenerateState()
{
var state = GenerateNonce();
AuthenticationProperties authProperties = new AuthenticationProperties
(
new Dictionary<string, string>
{
{ OpenIdConnectDefaults.UserstatePropertiesKey, state },
}
);
authProperties.RedirectUri = "http://localhost:5000";
//This StateDataFormat does not use the correct DataProtectionProvider
return openIdOptions.CurrentValue.StateDataFormat.Protect(authProperties);
}
Run Code Online (Sandbox Code Playgroud)
openIdOptions依赖注入在哪里。作为@inject IOptionsMonitor<OpenIdConnectOptions> openIdOptions
当我单击标记并触发自定义流时,SSO 端一切正常,但是当消息返回时,我收到以下错误:
An unhandled exception has occurred while executing the request.
System.Exception: An error was encountered while handling the remote login.
System.Exception: Unable to unprotect the message.State.
Run Code Online (Sandbox Code Playgroud)
这是从 OpenIdHandler抛出的,它调用Unprotect我认为与StateDataFormat之前注入的保护器相同的保护器:
Options.StateDataFormat.Unprotect(message.State);
从详细日志记录中,我在调用时看到以下内容GenerateState():
trce: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector[31]
Performing protect operation to key {cdf7e79b-8d1a-4e7e-a093-fea402dbba8c} with purposes ('/app/DataManager', 'Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler', '', 'v1').
Run Code Online (Sandbox Code Playgroud)
但是当请求回来时,我得到了 unprotect 日志:
trce: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector[5]
Performing unprotect operation to key {cdf7e79b-8d1a-4e7e-a093-fea402dbba8c} with purposes ('/app/DataManager', 'Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler', 'oidc', 'v1').
Run Code Online (Sandbox Code Playgroud)
主要区别在于 DataProtector 的“目的”不同(一个具有 '',一个具有 'oidc')。根据文档,这意味着它们的加密和解密方式不同。
我希望数据保护器是相同的,因为它们都指的是相同OpenIdConnectOptions的配置。
为什么两者DataProtector的目的不同?它们是不同的对象吗?我的配置中是否缺少某些内容?我如何从内部框架和我注入的内容中获得相同的提供者?
我有同样的问题并找到了答案,我们需要通过方案名称来获取正确的实例:
return _openIdOptions.Get("oidc").CurrentValue.StateDataFormat.Protect(authProperties);
Run Code Online (Sandbox Code Playgroud)