manfredsteyer / angular-oauth2-oidc

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

checkSession session_state with code flow and no silent refresh #1248

Open projectaki opened 2 years ago

projectaki commented 2 years ago

The issue I have found was with the oidc session management (checkSession) in case of code flow without silent refresh.

When the OP iframe responds with changed, a refresh token is used to get a new set of tokens, in case of error a logout is initiated. However I cannot find in the code where on successfull token refresh, we get the new session_state from OP (as far as the spec this is only received through an auth request, not a req to the token endpoint). This is listed in the oidc spec, that on changed a new id token is recieved together with a new session_state.

jeroenheijmans commented 2 years ago

I'm not sure if I entirely follow your post. There might also be a small language barrier at play? Perhaps you could clarify a bit more, and perhaps also add a "minimal sample" that demonstrates the situation you're running into? That should help the community help you further. (Mind you, the community is spread thin here on GitHub, there are not too many people answering questions.)

PS. It might also help to check some related issues? Perhaps one of them describes your situation as well?

projectaki commented 2 years ago

The below code is in the oauth-service.ts file. This method is fired during OpenID Connect Session Management, when the OP responds with a session changed postMessage.

  protected handleSessionChange(): void {
    this.eventsSubject.next(new OAuthInfoEvent('session_changed'));
    this.stopSessionCheckTimer();

    if (!this.useSilentRefresh && this.responseType === 'code') {
      this.refreshToken()
        .then((_) => {
          this.debug('token refresh after session change worked');
        })
        .catch((_) => {
          this.debug('token refresh did not work after session changed');
          this.eventsSubject.next(new OAuthInfoEvent('session_terminated'));
          this.logOut(true);
        });
    } else if (this.silentRefreshRedirectUri) {
      this.silentRefresh().catch((_) =>
        this.debug('silent refresh failed after session changed')
      );
      this.waitForSilentRefreshAfterSessionChange();
    } else {
      this.eventsSubject.next(new OAuthInfoEvent('session_terminated'));
      this.logOut(true);
    }
  }

when refreshToken() is called it will get new tokens from the OP, however it will not get a new session_state parameter, as this can only be returned in an authorize request, not a token request according to OpenID spec. My question is, how is the session_state supposed to be updated in this scenario?

Below is from oidc spec:

When the RP detects a session state change, it SHOULD first try a prompt=none request within an iframe to obtain a new ID Token and session state, sending the old ID Token as the id_token_hint. If the RP receives an ID token for the same End-User, it SHOULD simply update the value of the session state. If it does not receive an ID token or receives an ID token for another End-User, then it needs to handle this case as a logout for the original End-User. If the original End-User is already logged out at the RP when the state changes indicate that End-User should be logged out, the logout is considered to have succeeded.

Reference: OpenID Connect Session Management section 3.1

jeroenheijmans commented 2 years ago

Thanks for the clarification! I.... actually don't know the answer to your question. I (or someone from the community, or you yourself) would need to investigate what the answer is. I'll update the labels accordingly!