多个 IdentityServer 联合:错误无法取消保护消息。状态

Tar*_*bhi 9 authentication federation oauth-2.0 identityserver3 identityserver4

我正在尝试创建一个主从类型配置以使用 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
Run Code Online (Sandbox Code Playgroud)

我所有的应用程序和 api 都将指向MyMasterIdentityServer0并使用它进行身份验证

用户可以选择使用上述任何提供程序进行身份验证。他们可以选择用户名/密码,在这种情况下,他们应该被重定向到MySlaveIdentityServer1(基本身份验证),或者他们可以选择使用他们的 AD 帐户使用 Windows 身份验证,在这种情况下他们将被重定向到MySlaveIdentityServer2(Windows 身份验证),或者选择任何其他提供商。

用户通过身份验证后,他会从提供者服务器接收一个 id_token 并重定向回MyMasterIdentityServer0,在那里使用 Provider 和 ProviderUserId 查找外部用户,然后根据他的权限获得一个 access_token 以访问应用程序/api。

我面临的问题是 IdentityServer 主从配置对我不起作用,并且在用户在身份验证后重定向回主服务器时给我一个错误Unable to unprotect the message.State。我尝试查找问题,AuthO 也遇到了他们最近修复的相同错误。

收到错误

异常:无法取消对消息的保护。状态

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"
    //},
});
Run Code Online (Sandbox Code Playgroud)

基本身份验证服务器客户端配置

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" }
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

除了内部部署的 MySlaveIdentityServers 1、2、3 和 4 之外,所有身份验证提供程序都工作正常……甚至云演示身份服务器也工作正常。任何人都可以给我任何意见或建议吗?

tra*_*.js 22

我相信您收到Unable to unprotect the message.State错误是因为您的 OIDC 提供商之一试图解密/取消保护另一个的消息状态。(消息状态只是一个有助于安全的随机字符串。)

我建议您为每个 OIDC 提供商命名 AuthenticationSchemes ,如oidc-demooidc-master。然后外部提供者应该将您发送回相应的signin-oidc-demosignin-oidc-master端点。

——

原来这个答案基本上是正确的。使用多个 OIDC 提供商时,您需要不同的 AuthenticationSchemes ANDCallbackPath值:

.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";
    ...
  }
Run Code Online (Sandbox Code Playgroud)

请注意,身份验证中间件将神奇地处理任何CallbackPath已配置的内容,因此不需要显式处理。

如果您不区分 OIDC 提供者并使用单独的回调路径,他们可能会尝试使用相同的方案登录,并且加密将不匹配,并且只有在您的代码中注册的第一个 OIDC 提供者才能工作。

  • 很快是什么时候?已经四年了:) (8认同)