All files / src/utils/auth cognitoSession.ts

90% Statements 9/10
100% Branches 6/6
100% Functions 2/2
87.5% Lines 7/8

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46                                        107x     867x       867x 449x 449x   806x                       464x    
/**
 * Cheap, Amplify-free probe for an existing Cognito session.
 *
 * Public-homepage performance (perf/public-homepage-followup #2): aws-amplify (~426 KB)
 * is the largest remaining chunk on the homepage bundle. It is now lazy-loaded — but to
 * actually keep it off the wire for anonymous visitors, the eager code paths that would
 * otherwise pull it in (the API client's auth interceptor and AuthProvider's session
 * restore) must first decide whether there is even a session to restore, WITHOUT importing
 * Amplify.
 *
 * Amplify v6 persists its tokens under keys of the form
 * `CognitoIdentityServiceProvider.{clientId}.{username}.{tokenType}` in localStorage
 * ("remember me") or sessionStorage. A visitor who never logged in has none of these, so
 * scanning for the key prefix is a synchronous, dependency-free way to short-circuit before
 * the dynamic `import('aws-amplify/auth')`.
 *
 * This mirrors the storage-detection logic in `config/amplify.ts#detectTokenStorage`, kept
 * here as a standalone module so both `apiClient` and `AuthContext` can import it without
 * dragging in the Amplify config module's (type-only) dependency on aws-amplify.
 */
const COGNITO_KEY_PREFIX = 'CognitoIdentityServiceProvider.';
 
function storageHasCognitoToken(storage: Storage): boolean {
  try {
    // Iterate via the Storage API (length + key(i)) rather than Object.keys(storage):
    // Storage keys are not own-enumerable in every environment (notably jsdom), so
    // Object.keys would miss them. This form is correct in both browsers and tests.
    for (let i = 0; i < storage.length; i++) {
      const key = storage.key(i);
      if (key && key.startsWith(COGNITO_KEY_PREFIX)) return true;
    }
    return false;
  } catch {
    // Storage access can throw (e.g. disabled cookies / privacy mode). Treat as "no session".
    return false;
  }
}
 
/**
 * @returns true if Amplify-managed Cognito tokens exist in either localStorage or
 * sessionStorage — i.e. there is a session worth restoring and Amplify must be loaded.
 */
export function hasCognitoSession(): boolean {
  return storageHasCognitoToken(localStorage) || storageHasCognitoToken(sessionStorage);
}