c# - 如何获取 OpenIdConnectOptions StateDataFormat
问题描述
我有一个使用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;
});
基本的登录/注销流程按预期工作,没有任何问题。
我为使用自定义 SSO 功能而生成的自定义链接如下所示(剃刀):
<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>
使用定义的方法:
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);
}
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.
这是从 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').
但是当请求回来时,我得到了 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').
主要区别在于 DataProtector 的“用途”不同(一个具有 '' 和一个具有 'oidc')。根据文档,这意味着它们的加密和解密方式不同。
我希望数据保护器是相同的,因为它们都引用了相同OpenIdConnectOptions
的配置。
为什么两者DataProtector
提供不同的目的?它们是不同的对象吗?我的配置中是否缺少某些内容?如何从内部框架和我注入的内容中获得相同的提供者?
解决方案
我有同样的问题并找到了答案,我们需要通过方案名称来获取正确的实例:
return _openIdOptions.Get("oidc").CurrentValue.StateDataFormat.Protect(authProperties);
推荐阅读
- android - 按钮背景的十六进制颜色 - Kivy
- typescript - 声明模块和导入定义
- c# - 错误 CS1514:意外符号“公共”,应为“。” 或'{'
- python - Python Selenium:StaleElementReferenceException / 设置 aria-pressed = "true"
- node.js - 当我在 cmd 中使用 npm start 启动我的反应应用程序时,我收到以下错误
- python - Python多处理不会提高性能
- caching - 为 Cloud CDN 的对象禁用浏览器缓存时出错(通过 Google Cloud Storage 的存储桶)
- java - android api 19中的logcat出现错误有什么解决方案吗?
- php - 我的记录没有被插入 MySQL 数据库
- c# - 在 C# 中解码没有模式的 protobuf