多个 IdentityServer 联合:错误无法取消保护 message.State
Multiple IdentityServer Federation : Error Unable to unprotect the message.State
我正在尝试创建一个主从类型配置以使用 IdentityServer4 进行身份验证,如下所示
MyMasterIdentityServer0 (Master) - receives id_token and gives access_token
|---> MySlaveIdentityServer1 (Basic Auth)
|---> MySlaveIdentityServer2 (Windows Auth)
|---> MySlaveIdentityServer3 (SmartCard Certificate Auth)
|---> MySlaveIdentityServer4 (SAML SSO Auth)
|---> Cloud Demo IdentityServer
|---> Google Auth
|---> Facebook Auth
|---> Microsoft Auth
|---> Twitter Auth
我的所有应用程序和 api 都将指向 MyMasterIdentityServer0
并通过其进行身份验证
用户可以选择使用上述任何提供程序进行身份验证。他们可以选择 username/password,在这种情况下,他们应该被重定向到 MySlaveIdentityServer1(基本身份验证),或者他们可以选择使用 Windows 身份验证,使用他们的 AD 帐户在这种情况下,他们将被重定向到 MySlaveIdentityServer2 (Windows Auth),或选择任何其他提供商。
一旦用户通过身份验证,他就会从提供商服务器收到一个 id_token 并被重定向回 MyMasterIdentityServer0 ,在那里使用Provider 和 ProviderUserId,然后根据他的权限给予 access_token 访问 applications/api。
我面临的问题是 IdentityServer Master Slave 配置对我不起作用并且给我一个错误 Unable to unprotect the message.State 当用户在身份验证后被重定向回主服务器。我尝试查找问题,AuthO 也遇到了他们最近修复的相同错误。
收到错误
Exception: Unable to unprotect the message.State
IdentityServer-Master 配置
// WORKING
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "ID4DemoCloud",
DisplayName = "Login with ID4DemoCloud",
SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme,
SignOutScheme = IdentityServerConstants.SignoutScheme,
Authority = "https://demo.identityserver.io/",
ClientId = "implicit",
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
},
//Events = new OpenIdConnectEvents() { }
});
// NOT WORKING
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "MySlaveIdentityServer1BasicAuth",
DisplayName = "Login with MySlaveIdentityServer1 Basic Auth",
SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme,
SignOutScheme = IdentityServerConstants.SignoutScheme,
Authority = "http://localhost:5100/",
ClientId = "MyMasterIdentityServer0",
ClientSecret = "secret",
RequireHttpsMetadata = false,
//TokenValidationParameters = new TokenValidationParameters
//{
// NameClaimType = "name",
// RoleClaimType = "role"
//},
});
基本 Auth 服务器客户端配置
public static class Clients
{
public static IEnumerable<Client> GetClients()
{
return new[]
{
new Client
{
ClientId = "MyMasterIdentityServer0",
ClientName = "My Master IdentityServer 0",
ClientSecrets = new List<Secret> { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.Implicit,
AllowedScopes = new List<string>
{
StandardScopes.OpenId,
StandardScopes.Profile
},
RequireConsent = false,
AllowOfflineAccess = false,
RedirectUris = new [] { "http://localhost:5000/signin-oidc" }
}
};
}
}
除了内部部署的 MySlaveIdentityServers 1、2、3 和 4 之外,所有身份验证提供程序都工作正常......甚至 Cloud Demo Identity 服务器也工作正常。任何人都可以给我任何意见或建议吗?
我认为您遇到了 Unable to unprotect the message.State
错误,因为您的一个 OIDC 提供商正在尝试 decrypt/unprotect 另一个提供商的消息状态。 (消息状态只是一个随机字符串,以帮助提高安全性。)
我建议您为每个 OIDC 提供商命名 AuthenticationSchemes,例如 oidc-demo
和 oidc-master
。然后外部提供商应该将您发送回相应的 signin-oidc-demo
和 signin-oidc-master
端点。
--
原来这个答案基本上是正确的。使用多个 OIDC 提供商时,您需要不同的 AuthenticationSchemes 和 CallbackPath
值:
.AddOpenIdConnect("oidc-google", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.CallbackPath = "/signin-oidc-google";
...
}
.AddOpenIdConnect("oidc-microsoft", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.CallbackPath = "/signin-oidc-microsoft";
...
}
请注意,身份验证中间件会神奇地处理任何已配置的 CallbackPath
,因此不需要显式处理。
如果您不区分 OIDC 提供者并使用单独的回调路径,他们可能会尝试使用相同的方案登录,并且密码不会匹配,只有在您的代码中注册的第一个 OIDC 提供者才能工作。
我正在尝试创建一个主从类型配置以使用 IdentityServer4 进行身份验证,如下所示
MyMasterIdentityServer0 (Master) - receives id_token and gives access_token
|---> MySlaveIdentityServer1 (Basic Auth)
|---> MySlaveIdentityServer2 (Windows Auth)
|---> MySlaveIdentityServer3 (SmartCard Certificate Auth)
|---> MySlaveIdentityServer4 (SAML SSO Auth)
|---> Cloud Demo IdentityServer
|---> Google Auth
|---> Facebook Auth
|---> Microsoft Auth
|---> Twitter Auth
我的所有应用程序和 api 都将指向 MyMasterIdentityServer0
并通过其进行身份验证用户可以选择使用上述任何提供程序进行身份验证。他们可以选择 username/password,在这种情况下,他们应该被重定向到 MySlaveIdentityServer1(基本身份验证),或者他们可以选择使用 Windows 身份验证,使用他们的 AD 帐户在这种情况下,他们将被重定向到 MySlaveIdentityServer2 (Windows Auth),或选择任何其他提供商。
一旦用户通过身份验证,他就会从提供商服务器收到一个 id_token 并被重定向回 MyMasterIdentityServer0 ,在那里使用Provider 和 ProviderUserId,然后根据他的权限给予 access_token 访问 applications/api。
我面临的问题是 IdentityServer Master Slave 配置对我不起作用并且给我一个错误 Unable to unprotect the message.State 当用户在身份验证后被重定向回主服务器。我尝试查找问题,AuthO 也遇到了他们最近修复的相同错误。
收到错误
Exception: Unable to unprotect the message.State
IdentityServer-Master 配置
// WORKING
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "ID4DemoCloud",
DisplayName = "Login with ID4DemoCloud",
SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme,
SignOutScheme = IdentityServerConstants.SignoutScheme,
Authority = "https://demo.identityserver.io/",
ClientId = "implicit",
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
},
//Events = new OpenIdConnectEvents() { }
});
// NOT WORKING
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "MySlaveIdentityServer1BasicAuth",
DisplayName = "Login with MySlaveIdentityServer1 Basic Auth",
SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme,
SignOutScheme = IdentityServerConstants.SignoutScheme,
Authority = "http://localhost:5100/",
ClientId = "MyMasterIdentityServer0",
ClientSecret = "secret",
RequireHttpsMetadata = false,
//TokenValidationParameters = new TokenValidationParameters
//{
// NameClaimType = "name",
// RoleClaimType = "role"
//},
});
基本 Auth 服务器客户端配置
public static class Clients
{
public static IEnumerable<Client> GetClients()
{
return new[]
{
new Client
{
ClientId = "MyMasterIdentityServer0",
ClientName = "My Master IdentityServer 0",
ClientSecrets = new List<Secret> { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.Implicit,
AllowedScopes = new List<string>
{
StandardScopes.OpenId,
StandardScopes.Profile
},
RequireConsent = false,
AllowOfflineAccess = false,
RedirectUris = new [] { "http://localhost:5000/signin-oidc" }
}
};
}
}
除了内部部署的 MySlaveIdentityServers 1、2、3 和 4 之外,所有身份验证提供程序都工作正常......甚至 Cloud Demo Identity 服务器也工作正常。任何人都可以给我任何意见或建议吗?
我认为您遇到了 Unable to unprotect the message.State
错误,因为您的一个 OIDC 提供商正在尝试 decrypt/unprotect 另一个提供商的消息状态。 (消息状态只是一个随机字符串,以帮助提高安全性。)
我建议您为每个 OIDC 提供商命名 AuthenticationSchemes,例如 oidc-demo
和 oidc-master
。然后外部提供商应该将您发送回相应的 signin-oidc-demo
和 signin-oidc-master
端点。
--
原来这个答案基本上是正确的。使用多个 OIDC 提供商时,您需要不同的 AuthenticationSchemes 和 CallbackPath
值:
.AddOpenIdConnect("oidc-google", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.CallbackPath = "/signin-oidc-google";
...
}
.AddOpenIdConnect("oidc-microsoft", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.CallbackPath = "/signin-oidc-microsoft";
...
}
请注意,身份验证中间件会神奇地处理任何已配置的 CallbackPath
,因此不需要显式处理。
如果您不区分 OIDC 提供者并使用单独的回调路径,他们可能会尝试使用相同的方案登录,并且密码不会匹配,只有在您的代码中注册的第一个 OIDC 提供者才能工作。