@mrgnw/anahtar 0.0.24 → 0.0.25
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/kit/handlers.js +4 -4
- package/dist/passkey.d.ts +8 -5
- package/dist/passkey.js +18 -12
- package/dist/types.d.ts +5 -1
- package/package.json +1 -1
package/dist/kit/handlers.js
CHANGED
|
@@ -97,7 +97,7 @@ export function createHandlers(config) {
|
|
|
97
97
|
"passkey/login-start": {
|
|
98
98
|
method: "GET",
|
|
99
99
|
handler: async (event) => {
|
|
100
|
-
const options = await generateAuthenticationChallenge(config.db, event.url);
|
|
100
|
+
const options = await generateAuthenticationChallenge(config.db, event.url, config);
|
|
101
101
|
return json(options);
|
|
102
102
|
},
|
|
103
103
|
},
|
|
@@ -108,7 +108,7 @@ export function createHandlers(config) {
|
|
|
108
108
|
const email = body?.email;
|
|
109
109
|
if (!email || typeof email !== "string")
|
|
110
110
|
return json({ allowCredentials: [] });
|
|
111
|
-
const options = await generateAuthenticationChallengeForUser(config.db, email, event.url);
|
|
111
|
+
const options = await generateAuthenticationChallengeForUser(config.db, email, event.url, config);
|
|
112
112
|
return json(options);
|
|
113
113
|
},
|
|
114
114
|
},
|
|
@@ -119,7 +119,7 @@ export function createHandlers(config) {
|
|
|
119
119
|
const body = await event.request.json().catch(() => null);
|
|
120
120
|
if (!body)
|
|
121
121
|
return json({ error: m.errorInvalidInput }, { status: 400 });
|
|
122
|
-
const result = await verifyAuthenticationResponse(config.db, body, event.url);
|
|
122
|
+
const result = await verifyAuthenticationResponse(config.db, body, event.url, config);
|
|
123
123
|
if (!result)
|
|
124
124
|
return json({ error: m.errorAuthFailed }, { status: 401 });
|
|
125
125
|
const session = await createSession(config.db, result.user.id, config);
|
|
@@ -150,7 +150,7 @@ export function createHandlers(config) {
|
|
|
150
150
|
return json({ error: m.errorInvalidInput }, { status: 400 });
|
|
151
151
|
const { name, ...response } = body;
|
|
152
152
|
const passkeyName = typeof name === "string" && name.trim() ? name.trim() : null;
|
|
153
|
-
const result = await verifyRegistrationResponse(config.db, user.id, response, event.url, passkeyName);
|
|
153
|
+
const result = await verifyRegistrationResponse(config.db, user.id, response, event.url, passkeyName, config);
|
|
154
154
|
if (!result.ok) {
|
|
155
155
|
console.error("register-finish failed:", result.reason);
|
|
156
156
|
return json({ error: m.errorPasskeyRegFailed, reason: result.reason }, { status: 400 });
|
package/dist/passkey.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { AuthenticationResponseJSON, RegistrationResponseJSON } from "@simplewebauthn/server";
|
|
2
2
|
import type { AuthDB, ResolvedConfig } from "./types.js";
|
|
3
|
-
export declare function getWebAuthnConfig(requestUrl: URL
|
|
3
|
+
export declare function getWebAuthnConfig(requestUrl: URL, config?: {
|
|
4
|
+
rpId?: string;
|
|
5
|
+
origin?: string;
|
|
6
|
+
}): {
|
|
4
7
|
rpID: string;
|
|
5
8
|
origin: string;
|
|
6
9
|
};
|
|
@@ -8,15 +11,15 @@ export declare function generateRegistrationChallenge(db: AuthDB, user: {
|
|
|
8
11
|
id: string;
|
|
9
12
|
email: string;
|
|
10
13
|
}, requestUrl: URL, config: ResolvedConfig): Promise<import("@simplewebauthn/server").PublicKeyCredentialCreationOptionsJSON>;
|
|
11
|
-
export declare function verifyRegistrationResponse(db: AuthDB, userId: string, response: RegistrationResponseJSON, requestUrl: URL, name?: string | null): Promise<{
|
|
14
|
+
export declare function verifyRegistrationResponse(db: AuthDB, userId: string, response: RegistrationResponseJSON, requestUrl: URL, name?: string | null, config?: ResolvedConfig): Promise<{
|
|
12
15
|
ok: true;
|
|
13
16
|
} | {
|
|
14
17
|
ok: false;
|
|
15
18
|
reason: string;
|
|
16
19
|
}>;
|
|
17
|
-
export declare function generateAuthenticationChallengeForUser(db: AuthDB, email: string, requestUrl: URL): Promise<import("@simplewebauthn/server").PublicKeyCredentialRequestOptionsJSON>;
|
|
18
|
-
export declare function generateAuthenticationChallenge(db: AuthDB, requestUrl: URL): Promise<import("@simplewebauthn/server").PublicKeyCredentialRequestOptionsJSON>;
|
|
19
|
-
export declare function verifyAuthenticationResponse(db: AuthDB, response: AuthenticationResponseJSON, requestUrl: URL): Promise<{
|
|
20
|
+
export declare function generateAuthenticationChallengeForUser(db: AuthDB, email: string, requestUrl: URL, config?: ResolvedConfig): Promise<import("@simplewebauthn/server").PublicKeyCredentialRequestOptionsJSON>;
|
|
21
|
+
export declare function generateAuthenticationChallenge(db: AuthDB, requestUrl: URL, config?: ResolvedConfig): Promise<import("@simplewebauthn/server").PublicKeyCredentialRequestOptionsJSON>;
|
|
22
|
+
export declare function verifyAuthenticationResponse(db: AuthDB, response: AuthenticationResponseJSON, requestUrl: URL, config?: ResolvedConfig): Promise<{
|
|
20
23
|
user: {
|
|
21
24
|
id: string;
|
|
22
25
|
email: string;
|
package/dist/passkey.js
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { generateAuthenticationOptions, generateRegistrationOptions, verifyAuthenticationResponse as verifyAuthResponse, verifyRegistrationResponse as verifyRegResponse, } from "@simplewebauthn/server";
|
|
3
3
|
const CHALLENGE_EXPIRY_MS = 5 * 60 * 1000;
|
|
4
|
-
export function getWebAuthnConfig(requestUrl) {
|
|
4
|
+
export function getWebAuthnConfig(requestUrl, config) {
|
|
5
|
+
if (config?.rpId || config?.origin) {
|
|
6
|
+
return {
|
|
7
|
+
rpID: config.rpId ?? requestUrl.hostname,
|
|
8
|
+
origin: config.origin ?? requestUrl.origin,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
5
11
|
const envOrigin = process.env.ORIGIN;
|
|
6
12
|
if (envOrigin) {
|
|
7
13
|
const url = new URL(envOrigin);
|
|
@@ -10,7 +16,7 @@ export function getWebAuthnConfig(requestUrl) {
|
|
|
10
16
|
return { rpID: requestUrl.hostname, origin: requestUrl.origin };
|
|
11
17
|
}
|
|
12
18
|
export async function generateRegistrationChallenge(db, user, requestUrl, config) {
|
|
13
|
-
const { rpID } = getWebAuthnConfig(requestUrl);
|
|
19
|
+
const { rpID } = getWebAuthnConfig(requestUrl, config);
|
|
14
20
|
const existingPasskeys = await db.getUserPasskeys(user.id);
|
|
15
21
|
const excludeCredentials = existingPasskeys.map((pk) => ({
|
|
16
22
|
id: pk.credentialId,
|
|
@@ -33,8 +39,8 @@ export async function generateRegistrationChallenge(db, user, requestUrl, config
|
|
|
33
39
|
await db.storeChallenge(options.challenge, user.id, Date.now() + CHALLENGE_EXPIRY_MS);
|
|
34
40
|
return options;
|
|
35
41
|
}
|
|
36
|
-
export async function verifyRegistrationResponse(db, userId, response, requestUrl, name = null) {
|
|
37
|
-
const { rpID, origin } = getWebAuthnConfig(requestUrl);
|
|
42
|
+
export async function verifyRegistrationResponse(db, userId, response, requestUrl, name = null, config) {
|
|
43
|
+
const { rpID, origin } = getWebAuthnConfig(requestUrl, config);
|
|
38
44
|
let challenge;
|
|
39
45
|
try {
|
|
40
46
|
const clientData = JSON.parse(Buffer.from(response.response.clientDataJSON, "base64url").toString());
|
|
@@ -81,14 +87,14 @@ export async function verifyRegistrationResponse(db, userId, response, requestUr
|
|
|
81
87
|
return { ok: false, reason: `verification threw: ${e}` };
|
|
82
88
|
}
|
|
83
89
|
}
|
|
84
|
-
export async function generateAuthenticationChallengeForUser(db, email, requestUrl) {
|
|
85
|
-
const { rpID } = getWebAuthnConfig(requestUrl);
|
|
90
|
+
export async function generateAuthenticationChallengeForUser(db, email, requestUrl, config) {
|
|
91
|
+
const { rpID } = getWebAuthnConfig(requestUrl, config);
|
|
86
92
|
const user = await db.getUserByEmail(email);
|
|
87
93
|
if (!user)
|
|
88
|
-
return generateAuthenticationChallenge(db, requestUrl);
|
|
94
|
+
return generateAuthenticationChallenge(db, requestUrl, config);
|
|
89
95
|
const passkeys = await db.getUserPasskeys(user.id);
|
|
90
96
|
if (passkeys.length === 0)
|
|
91
|
-
return generateAuthenticationChallenge(db, requestUrl);
|
|
97
|
+
return generateAuthenticationChallenge(db, requestUrl, config);
|
|
92
98
|
const allowCredentials = passkeys.map((pk) => ({
|
|
93
99
|
id: pk.credentialId,
|
|
94
100
|
transports: pk.transports
|
|
@@ -103,8 +109,8 @@ export async function generateAuthenticationChallengeForUser(db, email, requestU
|
|
|
103
109
|
await db.storeChallenge(options.challenge, user.id, Date.now() + CHALLENGE_EXPIRY_MS);
|
|
104
110
|
return options;
|
|
105
111
|
}
|
|
106
|
-
export async function generateAuthenticationChallenge(db, requestUrl) {
|
|
107
|
-
const { rpID } = getWebAuthnConfig(requestUrl);
|
|
112
|
+
export async function generateAuthenticationChallenge(db, requestUrl, config) {
|
|
113
|
+
const { rpID } = getWebAuthnConfig(requestUrl, config);
|
|
108
114
|
const options = await generateAuthenticationOptions({
|
|
109
115
|
rpID,
|
|
110
116
|
allowCredentials: [],
|
|
@@ -113,8 +119,8 @@ export async function generateAuthenticationChallenge(db, requestUrl) {
|
|
|
113
119
|
await db.storeChallenge(options.challenge, "anonymous", Date.now() + CHALLENGE_EXPIRY_MS);
|
|
114
120
|
return options;
|
|
115
121
|
}
|
|
116
|
-
export async function verifyAuthenticationResponse(db, response, requestUrl) {
|
|
117
|
-
const { rpID, origin } = getWebAuthnConfig(requestUrl);
|
|
122
|
+
export async function verifyAuthenticationResponse(db, response, requestUrl, config) {
|
|
123
|
+
const { rpID, origin } = getWebAuthnConfig(requestUrl, config);
|
|
118
124
|
const passkey = await db.getPasskeyByCredentialId(response.id);
|
|
119
125
|
if (!passkey)
|
|
120
126
|
return null;
|
package/dist/types.d.ts
CHANGED
|
@@ -86,11 +86,15 @@ export interface AuthConfig {
|
|
|
86
86
|
otpLength?: number;
|
|
87
87
|
otpMaxAttempts?: number;
|
|
88
88
|
rpName?: string;
|
|
89
|
+
rpId?: string;
|
|
90
|
+
origin?: string;
|
|
89
91
|
locale?: string;
|
|
90
92
|
messages?: Partial<import('./i18n/types.js').AuthMessages>;
|
|
91
93
|
onSendOTP: (email: string, code: string) => Promise<void>;
|
|
92
94
|
}
|
|
93
|
-
export interface ResolvedConfig extends Required<Omit<AuthConfig, 'onSendOTP' | 'locale' | 'messages'>> {
|
|
95
|
+
export interface ResolvedConfig extends Required<Omit<AuthConfig, 'onSendOTP' | 'locale' | 'messages' | 'rpId' | 'origin'>> {
|
|
96
|
+
rpId?: string;
|
|
97
|
+
origin?: string;
|
|
94
98
|
locale?: string;
|
|
95
99
|
messages?: Partial<import('./i18n/types.js').AuthMessages>;
|
|
96
100
|
onSendOTP: (email: string, code: string) => Promise<void>;
|