Skip to content

Recover a lost config before a silent sign-in in the React SDK - #125

Merged
brionmario merged 1 commit into
thunder-id:mainfrom
brionmario:fix-silent-sign-in-endpoints
Oct 16, 2026
Merged

brionmario merged 1 commit into
thunder-id:mainfrom
brionmario:fix-silent-sign-in-endpoints

Conversation

@brionmario

Copy link
Copy Markdown
Member

Purpose

In the React SDK, the first signInSilently() on a page can fail straight away:

Error while signing in silently: Some or all of the required endpoints are missing in the object passed to the endpoints attribute of the AuthConfig object.

After a refresh, it works. I hit this in a Vite + React 19 sample running under <StrictMode>, against @thunderid/[email protected]. The call was rejected after 28 ms, before any iframe was created.

ThunderIDReactClient.signIn() already documents the cause:

With React 19 strict mode, the initialization logic runs twice, and there's an intermittent issue where the config object is not getting stored in the storage layer with Vite scaffolding.

signIn() re-runs initialization when it finds the stored config empty, but signInSilently() didn't. So a silent sign-in on an affected page read an empty config. With no baseUrl and no discovery URL, endpoint resolution fell through to resolveEndpointsExplicitly(), which threw the error above.

Approach

  • Shared recovery. The existing recovery moves into a private ensureConfigData(), now called by both signIn() and signInSilently().
  • Wider check. Besides an empty config, it also treats a stored config as lost when it no longer has the baseUrl the client was initialized with. That is the shape this error implies.
  • No root-cause fix. The underlying StrictMode storage race is still unexplained, and this PR doesn't try to fix it. It only stops silent sign-in from failing when the race strikes, the same way signIn() already does. Vue doesn't double-mount, so it doesn't have this workaround and doesn't need it.

Verification

  • New ThunderIDReactClient.configRecovery.test.ts covers three cases:
    • signInSilently() re-initializes when the stored config is missing;
    • it re-initializes when the config has lost its baseUrl;
    • it leaves an intact config alone.
  • The first two fail without the fix.
  • @thunderid/react tests pass (135). Typecheck and format are clean, and lint on ThunderIDReactClient.ts is unchanged.
  • Not verified in a browser: the race is intermittent, so I couldn't reproduce it on demand.

Cross-SDK parity: not needed. This is a React 19 StrictMode workaround in the React SDK only.

Related Issues

Related PRs

Checklist

  • Followed the contribution guidelines.
  • Manual test round performed and verified.
  • Documentation provided. (Add links if there are any)
  • Tests provided. (Add links if there are any)
    • Unit Tests
    • Integration Tests
  • Breaking changes. (Fill if applicable)
    • Breaking changes section filled.
    • breaking change label added.
  • Cross-SDK parity. Exactly one of parity/prs-raised or parity/prs-not-needed added.
    • If parity/prs-raised, the port links are posted as a reply on the parity check's comment.

Security checks

  • Followed secure coding standards.
  • Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets.

With React 19 strict mode the provider initializes the client twice,
and the config intermittently fails to land in storage. signIn()
already re-runs initialization when it finds the stored config empty,
but signInSilently() did not. The first silent sign-in on such a page
read an empty config, found neither a base URL nor a discovery
endpoint, and failed with "Some or all of the required endpoints are
missing". A refresh re-initialized cleanly, so it then worked.

Move the recovery into ensureConfigData() and call it from both
signIn() and signInSilently(). It also treats a stored config that has
lost the base URL it was initialized with as lost, not only an empty
one.

Signed-off-by: Brion <[email protected]>
@brionmario brionmario added the parity/prs-not-needed Nothing here reaches another SDK label Oct 16, 2026
@brionmario brionmario self-assigned this Oct 16, 2026
@coderabbitai

coderabbitai Bot commented Oct 16, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Repository: thunder-id/javascript-sdks/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b71e8bce-7c8e-49d2-aee5-0163f2bae395
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@brionmario
brionmario merged commit c18d20b into thunder-id:main Oct 16, 2026
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

parity/prs-not-needed Nothing here reaches another SDK

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants