manfredsteyer / angular-oauth2-oidc

Support for OAuth 2 and OpenId Connect (OIDC) in Angular.
MIT License
1.86k stars 681 forks source link

What is proper way to preserve/refresh login state, when redirecting back from other app after refresh_token exp time? #1407

Closed ddzingielewski closed 2 months ago

ddzingielewski commented 2 months ago

hi,

Describe the bug Its not a bug, but general/support question (so please forgive me clearing the default post headers).

Support request I have two angular apps: AppA and AppB. Both use angular-oauth2-oidc. Keycloak is the IDP. Here is the scenario: User logs in in AppA (code flow). At some point of time User (because of business logic) from AppA redirects to AppB. AppB logs in too thruu code flow. User works on AppB longer then AppA refresh_token exp. time. App B still has valid refresh_token thru silent refresh, and of course valid session exists on Keycloak. Now: User wants to redirect back to AppA.

The question: What is a proper way to preserve/refresh login state on AppA?

I managed it to work but in a bit weird/cumbersome way:


  const authConfig: AuthConfig = {
    issuer: [some issuer from config],
    redirectUri: window.location.origin + '/appContext/',
    clientId: 'the_client',
    responseType: 'code',
    scope: 'openid',
    showDebugInformation: true,
    waitForTokenInMsec: 300,
  };

  const isRedirect = funcToRecognizeRedirectFromAppB();

  oauthService.configure(authConfig);
  oauthService.setupAutomaticSilentRefresh();
  return from(oauthService.loadDiscoveryDocumentAndTryLogin()
    .then((_) => {
      if (oauthService.getRefreshToken()) {
        return oauthService.refreshToken()
          .then(() => {
            return Promise.resolve(true)
          } )
          .catch(() => { //so here I know that there was trouble with refresh_token
            if (isRedirect) { //here I know that i am currently redirecting from AppB
              sessionStorage.clear() //I need to clear it because if not "loadDiscoveryDocumentAndLogin" will try refresh access token using invalid refresh token
              return oauthService.loadDiscoveryDocumentAndLogin() //login automatically (I know that keycloak session exists)
              .then(() => {
                return Promise.resolve(true);
              })
              .catch(() => {
                return Promise.resolve(false);
              })
            }
            else {
              return Promise.resolve(false);
            }
          });
      }
      else {
        return Promise.resolve(false);
      }
    })
    .catch((err) => {
      return Promise.resolve(false);
    })).pipe(
      switchMap((flag) => {
        return someOtherInitOperations();
      }),
    )```

Is there any simpler way to check if session exists on keycloak and reauthenticate when no valid refresh_token (and without, for example, that ugly storage clearance?)
Thanks in advance for help.
ddzingielewski commented 2 months ago

Hi I figured out that when AppA and AppB are put to the same domain things are much more simpler. Both apps share storage (session storage) when is same domain, so refreshed tokens from AppB are visible by AppA and vice versa. I can use silent refresh and my code from previouse example shrinks to:

  const authConfig: AuthConfig = {
    issuer: [some issuer from config],
    redirectUri: window.location.origin + '/appContext/',
    clientId: 'the_client',
    responseType: 'code',
    scope: 'openid',
    showDebugInformation: true,
    waitForTokenInMsec: 300,
  };

  oauthService.configure(authConfig);
  oauthService.setupAutomaticSilentRefresh();
  return from(oauthService.loadDiscoveryDocumentAndTryLogin()).pipe(
      switchMap((flag) => {
        return someOtherInitOperations();
      }),
    )
ddzingielewski commented 2 months ago

As in my previous comment