@meith/accounts 0.33.4 → 0.35.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/package.json +3 -3
- package/src/federation/oidc.ts +6 -2
- package/src/memory-repos.ts +5 -4
- package/src/ports.ts +1 -1
- package/src/session-service.ts +5 -11
- package/src/webauthn/service.ts +5 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meith/accounts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"hash-wasm": "^4.12.0",
|
|
23
|
-
"@meith/i18n": "0.
|
|
24
|
-
"@meith/subscriptions": "0.
|
|
23
|
+
"@meith/i18n": "0.35.0",
|
|
24
|
+
"@meith/subscriptions": "0.35.0"
|
|
25
25
|
}
|
|
26
26
|
}
|
package/src/federation/oidc.ts
CHANGED
|
@@ -135,10 +135,14 @@ function profileFrom(claims: IdTokenClaims, userinfo: IdTokenClaims): ProviderPr
|
|
|
135
135
|
throw new ValidationError(msg('error.accounts.identity-provider-sent-account-with'))
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
const emailFromToken = stringClaim(claims, 'email')
|
|
139
|
+
const emailSource = emailFromToken !== null ? claims : userinfo
|
|
140
|
+
const email = emailFromToken ?? stringClaim(userinfo, 'email')
|
|
141
|
+
|
|
138
142
|
return {
|
|
139
143
|
subject,
|
|
140
|
-
email
|
|
141
|
-
emailVerified:
|
|
144
|
+
email,
|
|
145
|
+
emailVerified: email !== null && readBoolean(emailSource, 'email_verified'),
|
|
142
146
|
username:
|
|
143
147
|
stringClaim(merged, 'preferred_username') ??
|
|
144
148
|
stringClaim(merged, 'nickname') ??
|
package/src/memory-repos.ts
CHANGED
|
@@ -524,11 +524,12 @@ class MemoryPasskeys implements PasskeyRepository {
|
|
|
524
524
|
return true
|
|
525
525
|
}
|
|
526
526
|
|
|
527
|
-
async markUsed(passkeyId: number, signCount: number, now: Date): Promise<
|
|
527
|
+
async markUsed(passkeyId: number, signCount: number, now: Date): Promise<boolean> {
|
|
528
528
|
const record = this.byId.get(passkeyId)
|
|
529
|
-
if (record
|
|
530
|
-
|
|
531
|
-
}
|
|
529
|
+
if (record === undefined) return false
|
|
530
|
+
if (signCount !== 0 && signCount <= record.signCount) return false
|
|
531
|
+
this.byId.set(passkeyId, { ...record, signCount, lastUsedAt: now })
|
|
532
|
+
return true
|
|
532
533
|
}
|
|
533
534
|
}
|
|
534
535
|
|
package/src/ports.ts
CHANGED
|
@@ -230,7 +230,7 @@ export interface PasskeyRepository {
|
|
|
230
230
|
listForUser(userId: number): Promise<readonly PasskeyRecord[]>
|
|
231
231
|
create(input: NewPasskey): Promise<PasskeyRecord>
|
|
232
232
|
remove(userId: number, passkeyId: number): Promise<boolean>
|
|
233
|
-
markUsed(passkeyId: number, signCount: number, now: Date): Promise<
|
|
233
|
+
markUsed(passkeyId: number, signCount: number, now: Date): Promise<boolean>
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
export interface TwoFactorRecord {
|
package/src/session-service.ts
CHANGED
|
@@ -49,25 +49,19 @@ export class SessionService {
|
|
|
49
49
|
return this.mintSession(userId, this.now(), context)
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
async
|
|
52
|
+
async issueRemember(
|
|
53
|
+
userId: number,
|
|
54
|
+
): Promise<{ readonly rememberToken: string; readonly rememberExpiresAt: Date }> {
|
|
53
55
|
const at = this.now()
|
|
54
|
-
const familyId = generateToken()
|
|
55
56
|
const rememberToken = generateToken()
|
|
56
57
|
const rememberExpiresAt = new Date(at.getTime() + this.rememberDays * DAY_MS)
|
|
57
58
|
await this.store.remember.issue({
|
|
58
59
|
tokenHash: await hashToken(rememberToken),
|
|
59
|
-
familyId,
|
|
60
|
+
familyId: generateToken(),
|
|
60
61
|
userId,
|
|
61
62
|
expiresAt: rememberExpiresAt,
|
|
62
63
|
})
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
userId,
|
|
66
|
-
sessionToken: session.token,
|
|
67
|
-
sessionExpiresAt: session.expiresAt,
|
|
68
|
-
rememberToken,
|
|
69
|
-
rememberExpiresAt,
|
|
70
|
-
}
|
|
64
|
+
return { rememberToken, rememberExpiresAt }
|
|
71
65
|
}
|
|
72
66
|
|
|
73
67
|
async resume(rememberToken: string, context: RequestContext = {}): Promise<ResumeOutcome> {
|
package/src/webauthn/service.ts
CHANGED
|
@@ -194,8 +194,11 @@ export class PasskeyService {
|
|
|
194
194
|
throw new ForbiddenError(msg('error.accounts.account-behind-passkey-longer-exists'))
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
+
if (!(await this.passkeys.markUsed(passkey.id, verified.signCount, this.now()))) {
|
|
198
|
+
throw new ForbiddenError(msg('error.accounts.passkey-replayed-counter-board-already'))
|
|
199
|
+
}
|
|
200
|
+
|
|
197
201
|
const login = await this.identity.startSessionFor(account, input.context ?? {})
|
|
198
|
-
await this.passkeys.markUsed(passkey.id, verified.signCount, this.now())
|
|
199
202
|
|
|
200
203
|
return { account, login }
|
|
201
204
|
}
|
|
@@ -218,8 +221,7 @@ export class PasskeyService {
|
|
|
218
221
|
storedSignCount: passkey.signCount,
|
|
219
222
|
})
|
|
220
223
|
|
|
221
|
-
|
|
222
|
-
return true
|
|
224
|
+
return this.passkeys.markUsed(passkey.id, verified.signCount, this.now())
|
|
223
225
|
}
|
|
224
226
|
|
|
225
227
|
async remove(input: {
|