@mrgnw/anahtar 0.0.9 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/passkey.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { AuthenticationResponseJSON, RegistrationResponseJSON } from '@simplewebauthn/server';
2
- import type { AuthDB, ResolvedConfig } from './types.js';
1
+ import type { AuthenticationResponseJSON, RegistrationResponseJSON } from "@simplewebauthn/server";
2
+ import type { AuthDB, ResolvedConfig } from "./types.js";
3
3
  export declare function getWebAuthnConfig(requestUrl: URL): {
4
4
  rpID: string;
5
5
  origin: string;
package/dist/passkey.js CHANGED
@@ -1,5 +1,5 @@
1
- import { randomUUID } from 'node:crypto';
2
- import { generateAuthenticationOptions, generateRegistrationOptions, verifyAuthenticationResponse as verifyAuthResponse, verifyRegistrationResponse as verifyRegResponse } from '@simplewebauthn/server';
1
+ import { randomUUID } from "node:crypto";
2
+ import { generateAuthenticationOptions, generateRegistrationOptions, verifyAuthenticationResponse as verifyAuthResponse, verifyRegistrationResponse as verifyRegResponse, } from "@simplewebauthn/server";
3
3
  const CHALLENGE_EXPIRY_MS = 5 * 60 * 1000;
4
4
  export function getWebAuthnConfig(requestUrl) {
5
5
  const envOrigin = process.env.ORIGIN;
@@ -14,18 +14,21 @@ export async function generateRegistrationChallenge(db, user, requestUrl, config
14
14
  const existingPasskeys = await db.getUserPasskeys(user.id);
15
15
  const excludeCredentials = existingPasskeys.map((pk) => ({
16
16
  id: pk.credentialId,
17
- transports: pk.transports ? JSON.parse(pk.transports) : undefined
17
+ transports: pk.transports
18
+ ? JSON.parse(pk.transports)
19
+ : undefined,
18
20
  }));
19
21
  const options = await generateRegistrationOptions({
20
22
  rpName: config.rpName,
21
23
  rpID,
22
24
  userName: user.email,
25
+ userDisplayName: user.email,
23
26
  userID: new TextEncoder().encode(user.id),
24
27
  authenticatorSelection: {
25
- residentKey: 'required',
26
- userVerification: 'preferred'
28
+ residentKey: "required",
29
+ userVerification: "preferred",
27
30
  },
28
- excludeCredentials
31
+ excludeCredentials,
29
32
  });
30
33
  await db.storeChallenge(options.challenge, user.id, Date.now() + CHALLENGE_EXPIRY_MS);
31
34
  return options;
@@ -34,7 +37,7 @@ export async function verifyRegistrationResponse(db, userId, response, requestUr
34
37
  const { rpID, origin } = getWebAuthnConfig(requestUrl);
35
38
  let challenge;
36
39
  try {
37
- const clientData = JSON.parse(Buffer.from(response.response.clientDataJSON, 'base64url').toString());
40
+ const clientData = JSON.parse(Buffer.from(response.response.clientDataJSON, "base64url").toString());
38
41
  challenge = clientData.challenge;
39
42
  }
40
43
  catch (e) {
@@ -42,20 +45,24 @@ export async function verifyRegistrationResponse(db, userId, response, requestUr
42
45
  }
43
46
  const stored = await db.consumeChallenge(challenge);
44
47
  if (!stored)
45
- return { ok: false, reason: 'challenge not found or expired' };
48
+ return { ok: false, reason: "challenge not found or expired" };
46
49
  if (stored.userId !== userId)
47
- return { ok: false, reason: `userId mismatch: challenge=${stored.userId} session=${userId}` };
50
+ return {
51
+ ok: false,
52
+ reason: `userId mismatch: challenge=${stored.userId} session=${userId}`,
53
+ };
48
54
  try {
49
55
  const verification = await verifyRegResponse({
50
56
  response,
51
57
  expectedChallenge: challenge,
52
58
  expectedOrigin: origin,
53
- expectedRPID: rpID
59
+ expectedRPID: rpID,
60
+ requireUserVerification: false,
54
61
  });
55
62
  if (!verification.verified)
56
- return { ok: false, reason: 'verification not verified' };
63
+ return { ok: false, reason: "verification not verified" };
57
64
  if (!verification.registrationInfo)
58
- return { ok: false, reason: 'no registrationInfo' };
65
+ return { ok: false, reason: "no registrationInfo" };
59
66
  const { credential } = verification.registrationInfo;
60
67
  await db.storePasskey({
61
68
  id: randomUUID(),
@@ -63,8 +70,10 @@ export async function verifyRegistrationResponse(db, userId, response, requestUr
63
70
  credentialId: credential.id,
64
71
  publicKey: new Uint8Array(credential.publicKey),
65
72
  counter: credential.counter,
66
- transports: response.response.transports ? JSON.stringify(response.response.transports) : null,
67
- name
73
+ transports: response.response.transports
74
+ ? JSON.stringify(response.response.transports)
75
+ : null,
76
+ name,
68
77
  });
69
78
  return { ok: true };
70
79
  }
@@ -77,9 +86,9 @@ export async function generateAuthenticationChallenge(db, requestUrl) {
77
86
  const options = await generateAuthenticationOptions({
78
87
  rpID,
79
88
  allowCredentials: [],
80
- userVerification: 'preferred'
89
+ userVerification: "preferred",
81
90
  });
82
- await db.storeChallenge(options.challenge, 'anonymous', Date.now() + CHALLENGE_EXPIRY_MS);
91
+ await db.storeChallenge(options.challenge, "anonymous", Date.now() + CHALLENGE_EXPIRY_MS);
83
92
  return options;
84
93
  }
85
94
  export async function verifyAuthenticationResponse(db, response, requestUrl) {
@@ -87,7 +96,7 @@ export async function verifyAuthenticationResponse(db, response, requestUrl) {
87
96
  const passkey = await db.getPasskeyByCredentialId(response.id);
88
97
  if (!passkey)
89
98
  return null;
90
- const challenge = JSON.parse(Buffer.from(response.response.clientDataJSON, 'base64url').toString()).challenge;
99
+ const challenge = JSON.parse(Buffer.from(response.response.clientDataJSON, "base64url").toString()).challenge;
91
100
  const stored = await db.consumeChallenge(challenge);
92
101
  if (!stored)
93
102
  return null;
@@ -97,18 +106,21 @@ export async function verifyAuthenticationResponse(db, response, requestUrl) {
97
106
  expectedChallenge: challenge,
98
107
  expectedOrigin: origin,
99
108
  expectedRPID: rpID,
109
+ requireUserVerification: false,
100
110
  credential: {
101
111
  id: passkey.credentialId,
102
112
  publicKey: new Uint8Array(passkey.publicKey),
103
113
  counter: passkey.counter,
104
- transports: passkey.transports ? JSON.parse(passkey.transports) : undefined
105
- }
114
+ transports: passkey.transports
115
+ ? JSON.parse(passkey.transports)
116
+ : undefined,
117
+ },
106
118
  });
107
119
  if (!verification.verified)
108
120
  return null;
109
121
  await db.updatePasskeyCounter(passkey.id, verification.authenticationInfo.newCounter);
110
122
  return {
111
- user: { id: passkey.userId, email: passkey.email }
123
+ user: { id: passkey.userId, email: passkey.email },
112
124
  };
113
125
  }
114
126
  catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrgnw/anahtar",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "description": "Opinionated, reusable auth for SvelteKit. Email+OTP + passkeys.",
5
5
  "license": "MIT",
6
6
  "type": "module",