-
Notifications
You must be signed in to change notification settings - Fork 269
Description
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.
-
querySessionStatusis triggered and completes (usually failing quickly withlogin_requiredas expected in anonymous mode). -
signinSilentis 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.