Add login security retention and legal terms

This commit is contained in:
JB
2026-07-25 03:10:56 -04:00
parent 78dc5dcc98
commit 008d295ffb
16 changed files with 196 additions and 36 deletions
@@ -17,7 +17,7 @@ function bytes(value: unknown): Uint8Array<ArrayBuffer> {
throw new Error('Invalid passkey public key.');
}
export const POST: RequestHandler = async ({ cookies, request }) => {
export const POST: RequestHandler = async ({ cookies, request, getClientAddress }) => {
const body = await request.json() as { challengeId?: string; response?: AuthenticationResponseJSON };
if (!body.challengeId || !body.response) error(400, 'Incomplete passkey authentication.');
const database = await getDatabase();
@@ -31,7 +31,7 @@ export const POST: RequestHandler = async ({ cookies, request }) => {
const unavailable = passkey.deleted_at || passkey.blocked_at ||
(typeof passkey.banned_until === 'string' && new Date(passkey.banned_until) > new Date());
if (unavailable) {
await recordLogin(String(passkey.user_id), 'passkey', false);
await recordLogin(String(passkey.user_id), 'passkey', false, { request, getClientAddress, failureReason: 'account_restricted', credentialId: String(passkey.id) });
error(403, 'This account is not permitted to sign in.');
}
const transports = passkey.transports ? JSON.parse(String(passkey.transports)) as AuthenticatorTransportFuture[] : undefined;
@@ -44,14 +44,14 @@ export const POST: RequestHandler = async ({ cookies, request }) => {
requireUserVerification: true
});
if (!verification.verified) {
await recordLogin(String(passkey.user_id), 'passkey', false);
await recordLogin(String(passkey.user_id), 'passkey', false, { request, getClientAddress, failureReason: 'verification_failed', credentialId: String(passkey.id) });
error(400, 'Passkey authentication could not be verified.');
}
const now = new Date().toISOString();
await (await database.prepare('UPDATE passkeys SET counter=?,last_used_at=? WHERE id=?'))
.run(verification.authenticationInfo.newCounter, now, passkey.id);
await ensureBootstrapAdmin(database, String(passkey.user_id));
await createSession(cookies, String(passkey.user_id));
await recordLogin(String(passkey.user_id), 'passkey', true);
const sessionId = await createSession(cookies, String(passkey.user_id));
await recordLogin(String(passkey.user_id), 'passkey', true, { request, getClientAddress, credentialId: String(passkey.id), sessionId });
return json({ verified: true, redirectTo: '/account' });
};