fix(encryptid): handle non-JSON error responses in auth flow
When EncryptID server returns plain text errors (e.g. "Internal Server Error"), the client's .json() calls threw SyntaxError which surfaced as an ugly parse error to users. Add .catch() to all unsafe .json() calls in session.ts, login-button.ts, and recovery.ts so auth gracefully falls back to unsigned tokens instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
65b72ed7ac
commit
ca45eb43d2
|
|
@ -195,7 +195,7 @@ export class RecoveryManager {
|
||||||
throw new Error(err.error || `Server error: ${res.status}`);
|
throw new Error(err.error || `Server error: ${res.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await res.json();
|
const data = await res.json().catch(() => ({}));
|
||||||
serverId = data.guardian?.id;
|
serverId = data.guardian?.id;
|
||||||
|
|
||||||
console.log('EncryptID: Guardian added via server', {
|
console.log('EncryptID: Guardian added via server', {
|
||||||
|
|
@ -345,7 +345,7 @@ export class RecoveryManager {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const data = await res.json();
|
const data = await res.json().catch(() => ({ guardians: [] }));
|
||||||
const serverGuardian = data.guardians?.find((g: any) => g.id === guardianId);
|
const serverGuardian = data.guardians?.find((g: any) => g.id === guardianId);
|
||||||
|
|
||||||
if (!serverGuardian) {
|
if (!serverGuardian) {
|
||||||
|
|
|
||||||
|
|
@ -179,8 +179,9 @@ export class SessionManager {
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ credentialId: authResult.credentialId }),
|
body: JSON.stringify({ credentialId: authResult.credentialId }),
|
||||||
});
|
});
|
||||||
if (!startRes.ok) throw new Error('Failed to start server auth');
|
if (!startRes.ok) throw new Error(`Failed to start server auth: ${startRes.status}`);
|
||||||
const { options } = await startRes.json();
|
const startBody = await startRes.json().catch(() => { throw new Error('Invalid JSON from auth/start'); });
|
||||||
|
const { options } = startBody;
|
||||||
|
|
||||||
// Step 2: Complete auth with credentialId to get signed token
|
// Step 2: Complete auth with credentialId to get signed token
|
||||||
const completeRes = await fetch(`${ENCRYPTID_SERVER}/api/auth/complete`, {
|
const completeRes = await fetch(`${ENCRYPTID_SERVER}/api/auth/complete`, {
|
||||||
|
|
@ -191,8 +192,8 @@ export class SessionManager {
|
||||||
credential: { credentialId: authResult.credentialId },
|
credential: { credentialId: authResult.credentialId },
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
if (!completeRes.ok) throw new Error('Server auth failed');
|
if (!completeRes.ok) throw new Error(`Server auth failed: ${completeRes.status}`);
|
||||||
const data = await completeRes.json();
|
const data = await completeRes.json().catch(() => { throw new Error('Invalid JSON from auth/complete'); });
|
||||||
if (!data.token) throw new Error('No token in response');
|
if (!data.token) throw new Error('No token in response');
|
||||||
accessToken = data.token;
|
accessToken = data.token;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -544,7 +545,7 @@ export class SessionManager {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) throw new Error(`Refresh failed: ${res.status}`);
|
if (!res.ok) throw new Error(`Refresh failed: ${res.status}`);
|
||||||
const data = await res.json();
|
const data = await res.json().catch(() => { throw new Error('Invalid JSON from session/refresh'); });
|
||||||
if (!data.token) throw new Error('No token in refresh response');
|
if (!data.token) throw new Error('No token in refresh response');
|
||||||
|
|
||||||
// Decode new claims
|
// Decode new claims
|
||||||
|
|
|
||||||
|
|
@ -667,7 +667,9 @@ export class EncryptIDLoginButton extends HTMLElement {
|
||||||
body: JSON.stringify({ username }),
|
body: JSON.stringify({ username }),
|
||||||
});
|
});
|
||||||
if (!res.ok) return undefined;
|
if (!res.ok) return undefined;
|
||||||
const { options, userFound } = await res.json();
|
const body = await res.json().catch(() => null);
|
||||||
|
if (!body) return undefined;
|
||||||
|
const { options, userFound } = body;
|
||||||
if (!userFound || !options.allowCredentials?.length) return undefined;
|
if (!userFound || !options.allowCredentials?.length) return undefined;
|
||||||
return options.allowCredentials.map((c: any) => ({
|
return options.allowCredentials.map((c: any) => ({
|
||||||
type: 'public-key' as const,
|
type: 'public-key' as const,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue