tinyhumansai/openhuman · error

Sign-in callback was missing a token. Please try again.

Error message

Sign-in callback was missing a token. Please try again.

What it means

An openhuman://auth sign-in deep link arrived without a token query parameter, so there is nothing to exchange for a session — the flow fails fast with a user-facing message. This is the generic guard in handleAuthDeepLink (before the CSRF state check): the URL parsed successfully but carried no credential, typically a truncated/malformed redirect or a provider error redirect.

Source

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

  window.dispatchEvent(new CustomEvent(SESSION_TOKEN_UPDATED_EVENT, { detail: { sessionToken } }));
};

/**
 * Handle an `openhuman://auth?token=...` deep link for login.
 *
 * `requireStateNonce` defaults to true for genuine OS-registered custom-scheme
 * deep links (the finding C3 vector — any external app can trigger
 * `openhuman://`). The same-origin web callback route (`WebCallbackPage`) passes
 * `false`: it is reached only through the app's own routing / the backend OAuth
 * redirect on the same origin, not via the OS scheme, so it is outside C3's scope.
 */
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 {

View on GitHub (pinned to 7491200858)

Solutions

  1. Retry sign-in from the app — a fresh flow produces a well-formed callback URL
  2. If it repeats, inspect the redirected URL (browser address bar) for where the token parameter was dropped
  3. Check the backend OAuth redirect configuration for openhuman:// callback correctness
  4. The state nonce guard would also reject stale links; starting over is always safe
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at app/src/utils/desktopDeepLinkListener.ts:257 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/60c2d8c5aae59221. Report an issue: GitHub.