@mrgnw/anahtar 0.0.28 → 0.0.29-diagnostic.0
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/README.md +7 -1
- package/dist/passkey.js +20 -5
- package/package.json +15 -9
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# anahtar: incredibly simple & secure auth with passkeys and email+otp fallback
|
|
2
2
|
|
|
3
3
|
> **Pre-alpha.** API may change between releases.
|
|
4
4
|
|
|
@@ -13,6 +13,12 @@ Auth for SvelteKit. Email+OTP + optional passkeys.
|
|
|
13
13
|
3. First login -> passkey registration prompt
|
|
14
14
|
4. Future logins -> passkey autofill, OTP fallback
|
|
15
15
|
|
|
16
|
+
## Roadmap: Proof-of-concept: everything can change
|
|
17
|
+
The goal is simplicity, we will likely stay with passkeys and email+OTP only.
|
|
18
|
+
|
|
19
|
+
- we may change the implemenation.
|
|
20
|
+
- we will likely split the UI elements from the API, making it easier to run headless, just use the UI, or use both.
|
|
21
|
+
|
|
16
22
|
## Quick start
|
|
17
23
|
|
|
18
24
|
```sh
|
package/dist/passkey.js
CHANGED
|
@@ -121,13 +121,25 @@ export async function generateAuthenticationChallenge(db, requestUrl, config) {
|
|
|
121
121
|
}
|
|
122
122
|
export async function verifyAuthenticationResponse(db, response, requestUrl, config) {
|
|
123
123
|
const { rpID, origin } = getWebAuthnConfig(requestUrl, config);
|
|
124
|
+
const idHint = `${response.id.slice(0, 8)}…`;
|
|
124
125
|
const passkey = await db.getPasskeyByCredentialId(response.id);
|
|
125
|
-
if (!passkey)
|
|
126
|
+
if (!passkey) {
|
|
127
|
+
console.warn(`[anahtar login-finish] no stored passkey for credentialId=${idHint} (rpID=${rpID})`);
|
|
126
128
|
return null;
|
|
127
|
-
|
|
129
|
+
}
|
|
130
|
+
let challenge;
|
|
131
|
+
try {
|
|
132
|
+
challenge = JSON.parse(Buffer.from(response.response.clientDataJSON, "base64url").toString()).challenge;
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
console.warn(`[anahtar login-finish] clientDataJSON parse failed: ${e}`);
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
128
138
|
const stored = await db.consumeChallenge(challenge);
|
|
129
|
-
if (!stored)
|
|
139
|
+
if (!stored) {
|
|
140
|
+
console.warn(`[anahtar login-finish] challenge not found or expired (credentialId=${idHint})`);
|
|
130
141
|
return null;
|
|
142
|
+
}
|
|
131
143
|
try {
|
|
132
144
|
const verification = await verifyAuthResponse({
|
|
133
145
|
response,
|
|
@@ -144,14 +156,17 @@ export async function verifyAuthenticationResponse(db, response, requestUrl, con
|
|
|
144
156
|
: undefined,
|
|
145
157
|
},
|
|
146
158
|
});
|
|
147
|
-
if (!verification.verified)
|
|
159
|
+
if (!verification.verified) {
|
|
160
|
+
console.warn(`[anahtar login-finish] not verified (credentialId=${idHint}, expectedRPID=${rpID}, expectedOrigin=${origin})`);
|
|
148
161
|
return null;
|
|
162
|
+
}
|
|
149
163
|
await db.updatePasskeyCounter(passkey.id, verification.authenticationInfo.newCounter);
|
|
150
164
|
return {
|
|
151
165
|
user: { id: passkey.userId, email: passkey.email },
|
|
152
166
|
};
|
|
153
167
|
}
|
|
154
|
-
catch {
|
|
168
|
+
catch (e) {
|
|
169
|
+
console.warn(`[anahtar login-finish] verification threw (credentialId=${idHint}, expectedRPID=${rpID}, expectedOrigin=${origin}): ${e}`);
|
|
155
170
|
return null;
|
|
156
171
|
}
|
|
157
172
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrgnw/anahtar",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.29-diagnostic.0",
|
|
4
4
|
"description": "Opinionated, reusable auth for SvelteKit. Email+OTP + passkeys.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -12,6 +12,14 @@
|
|
|
12
12
|
"registry": "https://registry.npmjs.org/",
|
|
13
13
|
"access": "public"
|
|
14
14
|
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "svelte-package",
|
|
17
|
+
"check": "svelte-check --tsconfig ./tsconfig.json",
|
|
18
|
+
"test": "vitest run --config vitest.unit.ts && vitest run --config vitest.browser.ts",
|
|
19
|
+
"test:unit": "vitest run --config vitest.unit.ts",
|
|
20
|
+
"test:browser": "vitest run --config vitest.browser.ts",
|
|
21
|
+
"prepublishOnly": "pnpm build"
|
|
22
|
+
},
|
|
15
23
|
"svelte": "./dist/index.js",
|
|
16
24
|
"types": "./dist/index.d.ts",
|
|
17
25
|
"exports": {
|
|
@@ -60,6 +68,11 @@
|
|
|
60
68
|
"@oslojs/encoding": "^1.1.0",
|
|
61
69
|
"@simplewebauthn/server": "^13.2.2"
|
|
62
70
|
},
|
|
71
|
+
"pnpm": {
|
|
72
|
+
"onlyBuiltDependencies": [
|
|
73
|
+
"better-sqlite3"
|
|
74
|
+
]
|
|
75
|
+
},
|
|
63
76
|
"devDependencies": {
|
|
64
77
|
"@simplewebauthn/browser": "^13.2.2",
|
|
65
78
|
"@sveltejs/kit": "^2.31.1",
|
|
@@ -75,12 +88,5 @@
|
|
|
75
88
|
"svelte-check": "^4.3.1",
|
|
76
89
|
"typescript": "^5.9.2",
|
|
77
90
|
"vitest": "^3.2.1"
|
|
78
|
-
},
|
|
79
|
-
"scripts": {
|
|
80
|
-
"build": "svelte-package",
|
|
81
|
-
"check": "svelte-check --tsconfig ./tsconfig.json",
|
|
82
|
-
"test": "vitest run --config vitest.unit.ts && vitest run --config vitest.browser.ts",
|
|
83
|
-
"test:unit": "vitest run --config vitest.unit.ts",
|
|
84
|
-
"test:browser": "vitest run --config vitest.browser.ts"
|
|
85
91
|
}
|
|
86
|
-
}
|
|
92
|
+
}
|