diff --git a/app/api/admin/passkey/register/options/route.ts b/app/api/admin/passkey/register/options/route.ts index 8b467df..bf6ead2 100644 --- a/app/api/admin/passkey/register/options/route.ts +++ b/app/api/admin/passkey/register/options/route.ts @@ -49,11 +49,15 @@ export async function POST(request: NextRequest) { attestationType: "none", excludeCredentials, authenticatorSelection: { - residentKey: "preferred", + residentKey: "required", + requireResidentKey: true, userVerification: "preferred", authenticatorAttachment: "platform", }, supportedAlgorithmIDs: [-7, -257], // ES256, RS256 + extensions: { prf: {} } as Parameters< + typeof generateRegistrationOptions + >[0]["extensions"], }); // Store challenge in Redis with admin prefix diff --git a/lib/webauthn/config.ts b/lib/webauthn/config.ts index 640cb12..575c2b3 100644 --- a/lib/webauthn/config.ts +++ b/lib/webauthn/config.ts @@ -22,11 +22,16 @@ export function getRegistrationOptions( attestationType: "none", excludeCredentials, authenticatorSelection: { - residentKey: "preferred", + residentKey: "required", + requireResidentKey: true, userVerification: "preferred", authenticatorAttachment: "platform", }, supportedAlgorithmIDs: [-7, -257], // ES256, RS256 + // PRF extension isn't in @simplewebauthn's DOM types yet, but is passed + // through to the client and enables HKDF-based symmetric key derivation + // at authentication time (e.g. for E2EE key wrapping). + extensions: { prf: {} } as GenerateRegistrationOptionsOpts["extensions"], }; }