Files
chronus/src/pages/api/auth/passkey/register/start.ts
Atridad Lahiji e99e042eea
All checks were successful
Docker Deploy / build-and-push (push) Successful in 4m9s
Fixed Origin mismatch for passkeys
2026-02-13 11:35:06 -07:00

52 lines
1.4 KiB
TypeScript

import type { APIRoute } from "astro";
import { generateRegistrationOptions } from "@simplewebauthn/server";
import { db } from "../../../../../db";
import { passkeys, passkeyChallenges } from "../../../../../db/schema";
import { eq, lte } from "drizzle-orm";
import { getOrigin } from "../../../../../lib/auth";
export const GET: APIRoute = async ({ request, locals }) => {
const user = locals.user;
if (!user) {
return new Response(JSON.stringify({ error: "Unauthorized" }), {
status: 401,
});
}
await db
.delete(passkeyChallenges)
.where(lte(passkeyChallenges.expiresAt, new Date()));
const userPasskeys = await db.query.passkeys.findMany({
where: eq(passkeys.userId, user.id),
});
const { hostname } = getOrigin();
const options = await generateRegistrationOptions({
rpName: "Chronus",
rpID: hostname,
userName: user.email,
attestationType: "none",
excludeCredentials: userPasskeys.map((passkey) => ({
id: passkey.id,
transports: passkey.transports
? JSON.parse(passkey.transports)
: undefined,
})),
authenticatorSelection: {
residentKey: "preferred",
userVerification: "preferred",
},
});
await db.insert(passkeyChallenges).values({
challenge: options.challenge,
userId: user.id,
expiresAt: new Date(Date.now() + 5 * 60 * 1000),
});
return new Response(JSON.stringify(options));
};