4

When using any of the standard identity providers (Google, Facebook) after logging in and consent they redirect to my primary Identity Server and let it redirect to implicit client registered within it. How can I achieve the same behavior with another Identity Server serving as external identity provider?

My security architecture consists of two Identity Servers, primary one (v3) using the other (v4) as an external identity provider. The implicit client opens a popup with primary IdentityServer.

I have trouble with following flow:

Diagram showing authentication flow

Identity Server acting as external IdP gets stuck on endpoint:

/connect/authorize/login?client_id=primaryIdentityServer&redirect_uri=https://primaryIdentityServer.example.com/signin-oidc&response_mode=form_post&response_type=code id_token&scope=openid profile email

with error message:

Refused to send form data to 'https://jsclient.example.com/#(...)' because it violates the following Content Security Policy directive: "form-action https://primaryIdentityServer.example.com".

Primary IdentityServer configuration for external identity provider:

var opts = new OpenIdConnectAuthenticationOptions {
    ClientId = "primaryServer",
    ClientSecret = "secret",
    RedirectUri = "https://primaryIdentityServer.example.com/signin-oidc",
    Authority = "https://externalIdPIdentityServer.example.com",
    ResponseType = "code id_token",
    Scope = "openid profile email",
    SignInAsAuthenticationType = signInAsType
};

app.UseOpenIdConnectAuthentication(opts);

IdentityServer primary registered within IdentityServer serving as external IdP:

new Client
{
    ClientId = "primaryServer",
    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
    RedirectUris = new List<string>
    {
        "https://primaryIdentityServer.example.com/signin-oidc"
    },
    ClientSecrets = 
    {
        new Secret("secret".Sha256())
    },

    AllowedScopes =
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        IdentityServerConstants.StandardScopes.Email
    },
    AlwaysIncludeUserClaimsInIdToken = true
}

EDIT: I noticed when I try to check my app permissions on /permissions endpoint and authenticate using external IdentityServer I'm redirected to permission endpoint without any issues.

EDIT: I've tried switching to implicit flow between Identity Servers. Removed secrets, code from response_type and set implicit as allowed grant type and I still receive the same error with sending post data to my js client so it seems that selected flow (hybrid or implicit) is irrelevant for this issue.

EDIT: I've checked the source of the endpoint on which the authentication process is stuck:

<form method='post' action='https://primaryIdentityServer.example.com/signin-oidc'><input type='hidden' name='id_token' value='{token}' />
<input type='hidden' name='access_token' value='{token}' />
<input type='hidden' name='token_type' value='Bearer' />
<input type='hidden' name='expires_in' value='3600' />
<input type='hidden' name='scope' value='openid profile' />
<input type='hidden' name='state' value='OpenIdConnect.AuthenticationProperties={props}' />
<input type='hidden' name='session_state' value='{state}' />
</form><script>(function(){document.forms[0].submit();})();</script>

with query parameters: https://externalIdPIdentityServer.example.com/connect/authorize/consent?client_id=primaryServer&redirect_uri=https://primaryIdentityServer.example.com/signin-oidc&response_mode=form_post&response_type=token id_token&scope=openid profile&state={state}&nonce={nonce}

so its pretty weird why the error is:

Refused to send form data to 'https://jsclient.example.com/#(...)' because it violates the following Content Security Policy directive: "form-action https://primaryIdentityServer.example.com".

since jsclient.example.com isn't mentioned anywhere.

EDIT: Issue appears only in Chrome, not in Firefox or IE Edge.

Manikandan C
  • 668
  • 1
  • 9
  • 22
xmichaelx
  • 569
  • 1
  • 6
  • 17
  • 1
    Seems like you are redirecting back to the JavaScript client application instead of redirecting back to the primary identity server. This is mentioned in the content security policy which allows the external identity provider to post only to the primary identity provider that as it might have been sent the redirect URL at the client redirect URL which could have been the issue. HTH – Saravanan Jan 25 '17 at 15:00
  • Yes, I've come to the same conclusion. But I don't understand why that happens. Because both IdentityServers have only url of the primary one added as a valid redirect_url. I'd expect that they would exchange requests between themselves and the let the primary one redirect to my implicit js client. I expected behavior more in line with how Google or Facebook do it. You register your IdentityServer there, provide redirect urls and get client id and key :) – xmichaelx Jan 25 '17 at 15:05
  • There is a sample somewhere of idsvr acting as an external provider of another idsvr? ty – Renato Saito Apr 23 '17 at 20:20

1 Answers1

4

I've started searching for "chrome" and "csp" keywords in IdentityServer4 issues and found this one: https://github.com/IdentityServer/IdentityServer4/issues/659

Turns out that form-action CSP on authorize response needed to be changed and IdentityServer4 versions from 1.0.1 have this policy directive relaxed.

I updated IdentityServer4 from 1.0.0 to 1.0.2 and it solved the problem.

xmichaelx
  • 569
  • 1
  • 6
  • 17