Skip to content

Session Monitor initialization fails intermittently due to race condition with querySessionStatus and signinSilent calls #2279

@rogeriobatista-hotmart

Description

@rogeriobatista-hotmart

Hi there!

I'm currently using oidc-client-ts wrapped in a custom facade architecture (our internal cas-js library) to isolate our business rules and mitigate the impact of upstream core changes on our organization's applications.

I have observed indeterministic failure when initializing the application in anonymous mode during the first access (i.e., no active session at the OP/SSO). The Session Monitor often fails to start consistently.

📌 Observed Behavior and Symptoms

When the application starts, the following symptoms occur interchangeably, varying with each page refresh:

  • The Session Monitor intermittently fails to start in anonymous mode.

  • Sometimes a frame timeout occurs: [SessionMonitor] ErrorTimeout: IFrame timed out without a response.

  • Sometimes the SSO returns a 401 error related to the querySessionStatus call.

  • Sometimes the expected login_required error is returned, but the flow still fails to activate the Session Monitor consistently.

🔍 Root Cause Analysis: Concurrency

After inspecting network traffic and internal logs, I noticed that two separate, simultaneous requests are being dispatched to the SSO's /authorize endpoint upon application startup:

Request 1: Triggered internally by oidc-client-ts via querySessionStatus() (which is part of the SessionMonitor initialization).

Request 2: Triggered explicitly by our cas-js facade via signinSilent(). (This call is required at startup to fetch the user's access_token and profile and store them locally, as querySessionStatus does not handle local storage persistence).

These two requests are launched simultaneously with different state and code_challenge parameters. Our suspicion is that they are conflicting with each other in handling the OP's response or the browser's IFrame navigation state. The mechanism seems to fail if the response from one request is processed (or fails) while the other request's IFrame is still active.

✅ Functional Workaround

To test this concurrency hypothesis, I introduced a setTimeout to deliberately delay the signinSilent() call until after the querySessionStatus (triggered by the Session Monitor) has completed its check.

  1. querySessionStatus is triggered and completes (usually failing quickly with login_required as expected in anonymous mode).

  2. signinSilent is then executed afterwards.

Result: By introducing this forced synchronization, the problem disappears entirely, and the Session Monitor starts correctly in anonymous mode every time.

❓ Question for Discussion

Given that querySessionStatus is triggered automatically when the Session Monitor is initialized, and that an explicit signinSilent is needed by applications for local state persistence:

Is there an inherent problem or known conflict when these two processes simultaneously attempt to use the /authorize?prompt=none flow, or is there a recommended best practice for sequencing these calls that we might be missing in our facade layer?

Thank you for your help in clarifying this behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions