IdentityModel / oidc-client-js

OpenID Connect (OIDC) and OAuth2 protocol support for browser-based JavaScript applications
Apache License 2.0
2.43k stars 841 forks source link

signinRedirectCallback fails with "login_required" #1200

Closed martyt closed 3 years ago

martyt commented 4 years ago

We have two apps - an SPA and a legacy ASP.NET MVC (.NET Framework) app that both use our identity server application (.NET Core 3.1, IdentityServer 4.1) (in production, both apps are behind a gateway and appear to be just different urls on the same host; for local development, I use different ports on localhost for each app). Authentication is working fine - when we log into one app and then navigate to the other, the existing session is recognized and we are authenticated in both apps. So far so good.

However, we're having a strange problem on the SPA if the user logs out of the MVC app from a separate browser window -- Right after the MVC app logout is complete, our SPA's callback gets invoked (presumably by the check session iframe?). Callback then creates a userManager and invokes signinRedirectCallback(), however an exception is thrown from that call, with an error login_required

That seems to then start a loop where callback is called again, fails again and keeps rapidly repeating until the iframe timeout expires.

We use this configuration for userManager:

    const settings: UserManagerSettings = {
      authority: window.authEndpoint,
      automaticSilentRenew: false,
      client_id: "js",
      post_logout_redirect_uri: window.customUIAbsolutePath,
      redirect_uri: `${window.customUIAbsolutePath}/callback`,
      response_type: "code",
      revokeAccessTokenOnSignout: true,
      scope: "openid profile email role api1 IdentityServerApi",
    };

And on our identity server, the client is configured as

                new Client
                {
                    ClientId = "js",
                    ClientName = "JavaScript Client",
                    AllowedGrantTypes = GrantTypes.Code,
                    RequireClientSecret = false,
                    RequirePkce = true,
                    RedirectUris =
                    {
                        $"{customUIBaseUrl}/callback",
                    },

                    PostLogoutRedirectUris = { omniusUIBaseUrl, customUIBaseUrl },
                    AllowedCorsOrigins = { customUIDomain },

                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.Email,
                        JwtClaimTypes.Role,
                        IdentityServerConstants.LocalApi.ScopeName,
                        "api1",
                        "api2"
                    },

                    UpdateAccessTokenClaimsOnRefresh = true
                },

So, is this a bug in oidc-client or maybe a configuration error somewhere? If not, what is the correct way to handle the login_required failure response from signinRedirectCallback()?

brockallen commented 4 years ago

That error means that the request to the authorization endpoint via the iframe is not authenticated. The cookie is gone, invalid, expired, or simply not sent due to cross-site calls.

martyt commented 4 years ago

@brockallen Thanks for the explanation - it makes sense, as the user is really logged out at that point.

But if I don't do "something" to handle the error condition, I just end up in that rapid-fire loop until the iframe times out. Can you suggest an appropriate action in response to that error?

brockallen commented 4 years ago

Handle the userSignedOut event and do your cleanup there?

martyt commented 4 years ago

I'll give that a try. So I just let the iframe window timeout and ignore the errors?

drsmile1001 commented 4 years ago

Have same error too. Wonder how to handle it gracefully.

ultimaweapon commented 3 years ago

Listen for userSignedOut event works for me.

brockallen commented 3 years ago

I think you're all set on this now so closing.