{"record":{"id":"75ea2ec9ac19dd2f","repo":"wandb/openui","slug":"no-credential-id-found","errorCode":null,"errorMessage":"No credential ID found","messagePattern":"No credential ID found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/src/lib/webauthn.ts","lineNumber":100,"sourceCode":"\t)\n\t// TODO: might not work in windows\n\treturn crypto.subtle.importKey(\n\t\t'spki',\n\t\tpubKey,\n\t\t{\n\t\t\tname: 'ECDSA',\n\t\t\tnamedCurve: 'P-256',\n\t\t\thash: { name: 'SHA-256' }\n\t\t},\n\t\tfalse,\n\t\t['verify']\n\t)\n}\n\nexport const authenticate = async (id?: string) => {\n\tconst credentialID = id ?? window.localStorage.getItem('credentialID')\n\tif (credentialID === null) {\n\t\tthrow new Error('No credential ID found')\n\t}\n\n\tchallenge = random(32)\n\tconst credential = await navigator.credentials.get({\n\t\tpublicKey: {\n\t\t\tchallenge,\n\t\t\tallowCredentials: [\n\t\t\t\t{\n\t\t\t\t\tid: decode(credentialID),\n\t\t\t\t\ttype: 'public-key'\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t})\n\t// TODO: verify the assertion\n\tif (credential !== null) {\n\t\tconst cred = credential as PublicKeyCredential\n\t\tconst { clientDataJSON, authenticatorData, signature, userHandle } =","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/wandb/openui/blob/42d7ab4ab6650433486dfb12eb3783c393a3e475/frontend/src/lib/webauthn.ts#L82-L118","documentation":"authenticate() retrieves the stored credentialID from its argument or window.localStorage and requires one to start a WebAuthn get() ceremony. If neither exists it throws 'No credential ID found', meaning no passkey was ever registered (or the stored id was cleared) on this device/browser profile.","triggerScenarios":"Calling authenticate() with id undefined while localStorage.getItem('credentialID') returns null — e.g. fresh browser, cleared storage, private mode, or different origin than the one that registered.","commonSituations":"User registered a passkey on another device/browser; site data cleared; page served from a different domain/localhost port than registration; incognito browsing.","solutions":["Check localStorage for 'credentialID' before calling authenticate() and route to register() instead.","After a successful register(), persist navigator credential id as 'credentialID' in localStorage.","Serve the app from the same origin used during registration.","Catch this error and fall back to the registration flow."],"exampleFix":"// before\nawait authenticate()\n// after\nif (!localStorage.getItem('credentialID')) {\n  await register(username)\n} else {\n  await authenticate()\n}","handlingStrategy":"validation","validationCode":"function hasStoredCredential(): boolean {\n  return window.localStorage.getItem('credentialID') !== null\n}","typeGuard":null,"tryCatchPattern":"try {\n  await authenticate()\n} catch (e) {\n  if (e instanceof Error && e.message === 'No credential ID found') {\n    await register(username) // fall back to registration\n  }\n}","preventionTips":["Store credentialID in localStorage immediately after successful registration","Check hasStoredCredential() before offering passkey login","Remember storage is per-origin and per-browser-profile — same origin required","Fall back to registration when no credential exists"],"tags":["webauthn","localstorage","typescript","authentication"],"backgroundTag":"missing-credential-id","analyzedSha":"42d7ab4ab6650433486dfb12eb3783c393a3e475","analyzedAt":"2026-09-01T05:00:32.200Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}