Skip to content

[Bug]: storageCodeFlowInProgress flag never reset when checkAuthIncludingServer establishes session via SSO silent renew after an abandoned code flow #2221

Description

@jagipas

Version

21.0.0

Please provide a link to a minimal reproduction of the bug

No response

Please provide the exception or error you saw

No exception is thrown. The periodic token expiry check silently stops working. After a successful checkAuthIncludingServer call (which authenticates via iframe silent renew using an existing SSO session), the shouldStartPeriodicallyCheckForConfig method always returns false because isCodeFlowInProgress reads true from storage indefinitely. Tokens are never silently renewed after that point.

Steps to reproduce the behavior

1. Configure the library with silentRenew: true and useRefreshToken: false (iframe-based silent renew).
2. Call authorize() — the user is redirected to the Identity Provider. storageCodeFlowInProgress is set to true.
3. The user authenticates at the IdP (SSO session is established) but does not return via the expected authorization callback URL (e.g. navigates directly back to the app root).
4. The app calls checkAuthIncludingServer(). Since there are no local tokens, checkAuthWithConfig returns isAuthenticated: false.
5. forceRefreshSession is called and successfully retrieves tokens via iframe silent renew (SSO session exists at the IdP).
6. The user is now authenticated with valid tokens in storage.
7. Observe that startTokenValidationPeriodically never triggers a token refresh — shouldStartPeriodicallyCheckForConfig always returns false.

A clear and concise description of what you expected to happen.

After checkAuthIncludingServer successfully authenticates the user via silent renew, the periodic token check should work normally and silently renew tokens before they expire, just as it would after a regular checkAuth callback flow.

Additional context

The root cause is that resetCodeFlowInProgress is only called inside CodeFlowCallbackService.authenticatedCallbackWithCode (code-flow-callback.service.ts:32), which is only reached when the current URL contains an authorization code (i.e. [isCallback === true]). When the code flow is abandoned and checkAuthIncludingServertakes the forceRefreshSessionpath instead, resetCodeFlowInProgress is never called, leaving storageCodeFlowInProgress = true in storage permanently.

Contrast this with isSilentRenewRunning which has a built-in timeout mechanism (silentRenewTimeoutInSeconds) that self-heals if the process gets stuck. isCodeFlowInProgress has no equivalent safeguard.

Suggested fix — reset the flag in checkAuthWithConfig when no callback is detected, since that implies any previously started code flow was abandoned:

// check-auth.service.ts — checkAuthWithConfig
const isCallback = this.callbackService.isCallback(currentUrl, config);

if (!isCallback) {
  this.flowsDataService.resetCodeFlowInProgress(config);
}

This is the minimal, defensive fix: if the app loads without a callback URL, there is no in-flight code flow to protect, so the flag should always be cleared.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions