Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

authentication - Multiple IdentityServer Federation : Error Unable to unprotect the message.State

I'm trying to create a master slave type configuration for authentication with IdentityServer4 as below

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

All my applications and api will point to and authenticate with the MyMasterIdentityServer0

Users can have a choice of authentication using any of the above providers. They can choose username/password in which case they should be redirected to the MySlaveIdentityServer1 (Basic Auth), or they can choose using the Windows Auth using their AD account in which case they will be redirected to MySlaveIdentityServer2 (Windows Auth), or choose any other provider.

Once the user has been authenticated, he receives an id_token from the provider server and gets redirected back to the MyMasterIdentityServer0 where the external user is looked up using the Provider and ProviderUserId and then given an access_token to access the applications/api based on his permissions.

They problem I'm facing is that the IdentityServer Master Slave configuration is not working for me and is giving me an error Unable to unprotect the message.State when the user is redirected back to the master server after authentication. I tried looking up the issue and AuthO also faced this same bug which they recently fixed.

Error Received

Exception: Unable to unprotect the message.State

IdentityServer-Master Configuration

// 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"
    //},
});

Basic Auth Server Client Configuration

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" }
            }
        };
    }
}

All the auth providers are working fine except the internally deployed MySlaveIdentityServers 1, 2, 3 and 4 ... even the Cloud Demo Identity server is working fine. Can anyone give me any advice or suggestions ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I believe you are getting the Unable to unprotect the message.State error because one of your OIDC providers is trying to decrypt/unprotect the message state of the other one. (The message state is just a random string to help with security.)

I suggest that you name the AuthenticationSchemes for each OIDC provider like oidc-demo and oidc-master. Then the external providers should send you back to the corresponding signin-oidc-demo and signin-oidc-master endpoints.

--

Turns out this answer was basically, correct. When using multiple OIDC providers you need different AuthenticationSchemes AND CallbackPath values:

.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";
    ...
  }

Note that the authentication middleware will magically handle any CallbackPath that's configured, so it doesn't need to be handled explicitly.

If you don't differentiate OIDC providers and use separate callback paths, they may try to sign in with the same scheme and the cryptography won't match and only the first OIDC provider registered in your code will work.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...