Add passkey and magic link authentication
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
import { getSessionUser } from '$lib/server/auth/session';
|
||||
import { consumeChallenge } from '$lib/server/auth/passkeys';
|
||||
import { getDatabase } from '$lib/server/database';
|
||||
import { verifyRegistrationResponse, type RegistrationResponseJSON } from '@simplewebauthn/server';
|
||||
import { error, json } from '@sveltejs/kit';
|
||||
import { Buffer } from 'node:buffer';
|
||||
import type { RequestHandler } from './$types';
|
||||
|
||||
export const POST: RequestHandler = async ({ cookies, request }) => {
|
||||
const user = await getSessionUser(cookies);
|
||||
if (!user) error(401, 'Sign in before registering a passkey.');
|
||||
const body = await request.json() as { challengeId?: string; name?: string; response?: RegistrationResponseJSON };
|
||||
if (!body.challengeId || !body.response) error(400, 'Incomplete passkey registration.');
|
||||
const database = await getDatabase();
|
||||
const challenge = await consumeChallenge(database, body.challengeId, 'registration', user.id);
|
||||
if (!challenge) error(400, 'The passkey registration expired. Try again.');
|
||||
const verification = await verifyRegistrationResponse({
|
||||
response: body.response,
|
||||
expectedChallenge: String(challenge.challenge),
|
||||
expectedOrigin: String(challenge.origin),
|
||||
expectedRPID: String(challenge.rp_id),
|
||||
requireUserVerification: true
|
||||
});
|
||||
if (!verification.verified || !verification.registrationInfo) error(400, 'Passkey registration could not be verified.');
|
||||
const { credential, credentialDeviceType, credentialBackedUp } = verification.registrationInfo;
|
||||
const name = String(body.name || 'My passkey').trim().slice(0, 60) || 'My passkey';
|
||||
await (await database.prepare(`INSERT INTO passkeys(id,user_id,webauthn_user_id,public_key,counter,device_type,backed_up,transports,name,created_at)
|
||||
VALUES(?,?,?,?,?,?,?,?,?,?)`)).run(
|
||||
credential.id, user.id, Buffer.from(user.id).toString('base64url'),
|
||||
credential.publicKey, credential.counter, credentialDeviceType, credentialBackedUp ? 1 : 0,
|
||||
credential.transports ? JSON.stringify(credential.transports) : null, name, new Date().toISOString()
|
||||
);
|
||||
return json({ verified: true });
|
||||
};
|
||||
Reference in New Issue
Block a user