UNPKG

payload-auth-plugin

Version:
75 lines (74 loc) 2.57 kB
// src/core/protocols/passkey/registration.ts import { parseCookies } from "payload"; import { generateRegistrationOptions, verifyRegistrationResponse } from "@simplewebauthn/server"; import { PasskeyVerificationAPIError } from "../../errors/apiErrors.js"; import { MissingOrInvalidSession } from "../../errors/consoleErrors.js"; import { hashCode } from "../../utils/hash.js"; async function GeneratePasskeyRegistration(request, rpID) { const { data } = await request.json(); const registrationOptions = { rpName: "Payload Passkey Webauth", rpID, userName: data.email, timeout: 60000, attestationType: "none", authenticatorSelection: { residentKey: "required", userVerification: "required" }, supportedAlgorithmIDs: [-7, -257] }; const options = await generateRegistrationOptions(registrationOptions); const cookieMaxage = new Date(Date.now() + 300 * 1000); const cookies = []; cookies.push(`__session-webpk-challenge=${options.challenge};Path=/;HttpOnly;SameSite=lax;Expires=${cookieMaxage.toUTCString()}`); const res = new Response(JSON.stringify({ options }), { status: 201 }); cookies.forEach((cookie) => { res.headers.append("Set-Cookie", cookie); }); return res; } async function VerifyPasskeyRegistration(request, rpID, session_callback) { try { const parsedCookies = parseCookies(request.headers); const challenge = parsedCookies.get("__session-webpk-challenge"); if (!challenge) { throw new MissingOrInvalidSession; } const body = await request.json(); const verification = await verifyRegistrationResponse({ response: body.data.registration, expectedChallenge: challenge, expectedOrigin: request.payload.config.serverURL, expectedRPID: rpID }); if (!verification.verified) { throw new PasskeyVerificationAPIError; } const { credential, credentialDeviceType, credentialBackedUp } = verification.registrationInfo; return await session_callback({ sub: hashCode(body.data.email + request.payload.secret).toString(), name: "", picture: "", email: body.data.email, passKey: { credentialId: credential.id, publicKey: credential.publicKey, counter: credential.counter, transports: credential.transports, deviceType: credentialDeviceType, backedUp: credentialBackedUp } }); } catch (error) { console.error(error); return Response.json({}); } } export { VerifyPasskeyRegistration, GeneratePasskeyRegistration };