@mrgnw/anahtar 0.0.7 → 0.0.9
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/components/AuthFlow.svelte +2 -2
- package/dist/kit/handlers.js +5 -3
- package/dist/passkey.d.ts +6 -1
- package/dist/passkey.js +19 -8
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { guessDeviceName } from '../device.js';
|
|
3
|
-
import
|
|
3
|
+
import OtpInput from './OtpInput.svelte';
|
|
4
4
|
import PasskeyPrompt from './PasskeyPrompt.svelte';
|
|
5
5
|
|
|
6
6
|
interface Props {
|
|
@@ -15,7 +15,7 @@ let congratsTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
|
15
15
|
let email = $state('');
|
|
16
16
|
let loading = $state(false);
|
|
17
17
|
let error = $state('');
|
|
18
|
-
let otpInput = $state<
|
|
18
|
+
let otpInput = $state<{ clear: () => void; focus: () => void }>();
|
|
19
19
|
|
|
20
20
|
let conditionalAbort: AbortController | null = null;
|
|
21
21
|
|
package/dist/kit/handlers.js
CHANGED
|
@@ -119,9 +119,11 @@ export function createHandlers(config) {
|
|
|
119
119
|
return json({ error: 'Invalid input' }, { status: 400 });
|
|
120
120
|
const { name, ...response } = body;
|
|
121
121
|
const passkeyName = typeof name === 'string' && name.trim() ? name.trim() : null;
|
|
122
|
-
const
|
|
123
|
-
if (!
|
|
124
|
-
|
|
122
|
+
const result = await verifyRegistrationResponse(config.db, user.id, response, event.url, passkeyName);
|
|
123
|
+
if (!result.ok) {
|
|
124
|
+
console.error('register-finish failed:', result.reason);
|
|
125
|
+
return json({ error: 'Passkey registration failed', reason: result.reason }, { status: 400 });
|
|
126
|
+
}
|
|
125
127
|
return json({ success: true });
|
|
126
128
|
}
|
|
127
129
|
},
|
package/dist/passkey.d.ts
CHANGED
|
@@ -8,7 +8,12 @@ export declare function generateRegistrationChallenge(db: AuthDB, user: {
|
|
|
8
8
|
id: string;
|
|
9
9
|
email: string;
|
|
10
10
|
}, 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<
|
|
11
|
+
export declare function verifyRegistrationResponse(db: AuthDB, userId: string, response: RegistrationResponseJSON, requestUrl: URL, name?: string | null): Promise<{
|
|
12
|
+
ok: true;
|
|
13
|
+
} | {
|
|
14
|
+
ok: false;
|
|
15
|
+
reason: string;
|
|
16
|
+
}>;
|
|
12
17
|
export declare function generateAuthenticationChallenge(db: AuthDB, requestUrl: URL): Promise<import("@simplewebauthn/server").PublicKeyCredentialRequestOptionsJSON>;
|
|
13
18
|
export declare function verifyAuthenticationResponse(db: AuthDB, response: AuthenticationResponseJSON, requestUrl: URL): Promise<{
|
|
14
19
|
user: {
|
package/dist/passkey.js
CHANGED
|
@@ -32,10 +32,19 @@ export async function generateRegistrationChallenge(db, user, requestUrl, config
|
|
|
32
32
|
}
|
|
33
33
|
export async function verifyRegistrationResponse(db, userId, response, requestUrl, name = null) {
|
|
34
34
|
const { rpID, origin } = getWebAuthnConfig(requestUrl);
|
|
35
|
-
|
|
35
|
+
let challenge;
|
|
36
|
+
try {
|
|
37
|
+
const clientData = JSON.parse(Buffer.from(response.response.clientDataJSON, 'base64url').toString());
|
|
38
|
+
challenge = clientData.challenge;
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
return { ok: false, reason: `clientDataJSON parse failed: ${e}` };
|
|
42
|
+
}
|
|
36
43
|
const stored = await db.consumeChallenge(challenge);
|
|
37
|
-
if (!stored
|
|
38
|
-
return false;
|
|
44
|
+
if (!stored)
|
|
45
|
+
return { ok: false, reason: 'challenge not found or expired' };
|
|
46
|
+
if (stored.userId !== userId)
|
|
47
|
+
return { ok: false, reason: `userId mismatch: challenge=${stored.userId} session=${userId}` };
|
|
39
48
|
try {
|
|
40
49
|
const verification = await verifyRegResponse({
|
|
41
50
|
response,
|
|
@@ -43,8 +52,10 @@ export async function verifyRegistrationResponse(db, userId, response, requestUr
|
|
|
43
52
|
expectedOrigin: origin,
|
|
44
53
|
expectedRPID: rpID
|
|
45
54
|
});
|
|
46
|
-
if (!verification.verified
|
|
47
|
-
return false;
|
|
55
|
+
if (!verification.verified)
|
|
56
|
+
return { ok: false, reason: 'verification not verified' };
|
|
57
|
+
if (!verification.registrationInfo)
|
|
58
|
+
return { ok: false, reason: 'no registrationInfo' };
|
|
48
59
|
const { credential } = verification.registrationInfo;
|
|
49
60
|
await db.storePasskey({
|
|
50
61
|
id: randomUUID(),
|
|
@@ -55,10 +66,10 @@ export async function verifyRegistrationResponse(db, userId, response, requestUr
|
|
|
55
66
|
transports: response.response.transports ? JSON.stringify(response.response.transports) : null,
|
|
56
67
|
name
|
|
57
68
|
});
|
|
58
|
-
return true;
|
|
69
|
+
return { ok: true };
|
|
59
70
|
}
|
|
60
|
-
catch {
|
|
61
|
-
return false;
|
|
71
|
+
catch (e) {
|
|
72
|
+
return { ok: false, reason: `verification threw: ${e}` };
|
|
62
73
|
}
|
|
63
74
|
}
|
|
64
75
|
export async function generateAuthenticationChallenge(db, requestUrl) {
|