tinyhumansai/openhuman · error

Sign-in could not be verified. Please start sign-in again.

Error message

Sign-in could not be verified. Please start sign-in again.

What it means

The auth deep link's CSRF/session-fixation guard (finding C3) rejected the callback: the token was present but the state parameter did not match a nonce this app generated before starting the flow (or was missing when required — requireStateNonce is true for OS-registered openhuman:// links). The link is not honoured and the user is told to restart sign-in; this blocks another app from forging an openhuman://auth link that logs the victim into an attacker-chosen session.

Source

Thrown at app/src/utils/desktopDeepLinkListener.ts:269

const handleAuthDeepLink = async (parsed: URL, requireStateNonce = true) => {
  const token = parsed.searchParams.get('token');
  const key = parsed.searchParams.get('key');
  const state = parsed.searchParams.get('state');
  if (!token) {
    console.warn('[DeepLink] URL did not contain a token query parameter');
    failDeepLinkAuthProcessing('Sign-in callback was missing a token. Please try again.');
    return;
  }

  // CSRF / session-fixation guard (finding C3): only honour an auth deep link
  // whose `state` matches a nonce this app generated before starting the flow.
  // This is what stops a hostile page from triggering the OS custom scheme
  // `openhuman://auth?token=<attacker_jwt>&key=auth` and silently logging the
  // victim into the attacker's account. The `key=auth` raw-JWT path in
  // particular is ONLY safe behind this check on the custom-scheme transport.
  if (requireStateNonce && !verifyAndConsumeAuthDeepLinkState(state)) {
    console.warn('[DeepLink][auth] rejecting auth deep link: missing or unrecognized state nonce');
    failDeepLinkAuthProcessing('Sign-in could not be verified. Please start sign-in again.');
    return;
  }

  beginDeepLinkAuthProcessing();

  try {
    await focusMainWindow();

    const readiness = await waitForOAuthAuthReadiness();
    if (!readiness.ready) {
      console.warn('[DeepLink][auth] OAuth readiness gate blocked login', readiness);
      failDeepLinkAuthProcessing(oauthAuthReadinessUserMessage(readiness.reason));
      return;
    }

    const sessionToken = key === 'auth' ? token : await consumeLoginToken(token);
    await applySessionToken(sessionToken);

View on GitHub (pinned to 7491200858)

Solutions

  1. Start sign-in again from the app — the retry pairs a fresh nonce with a fresh callback
  2. Never reuse an old callback URL: its state nonce was consumed or never issued by this instance
  3. If genuinely initiated by this app and still failing, check that the app wasn't restarted between flow start and callback (restart clears nonces)
  4. Report repeated legit-flow failures — the nonce store may be dropping entries
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at app/src/utils/desktopDeepLinkListener.ts:269 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/1d44c6eceb51c282. Report an issue: GitHub.