@hilbras/keystone 1.9.0 → 2.6.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/CHANGELOG.md +459 -0
- package/README.md +163 -32
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -0
- package/dist/config.js.map +1 -1
- package/dist/db/migrations/0015_chief_vargas.sql +7 -0
- package/dist/db/migrations/0016_gorgeous_charles_xavier.sql +5 -0
- package/dist/db/migrations/0017_flashy_nekra.sql +1 -0
- package/dist/db/migrations/meta/0015_snapshot.json +4340 -0
- package/dist/db/migrations/meta/0016_snapshot.json +4363 -0
- package/dist/db/migrations/meta/0017_snapshot.json +4370 -0
- package/dist/db/migrations/meta/_journal.json +21 -0
- package/dist/db/schema.d.ts +138 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +39 -1
- package/dist/db/schema.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/plugins/auth.d.ts +2 -0
- package/dist/plugins/auth.d.ts.map +1 -1
- package/dist/plugins/auth.js +21 -7
- package/dist/plugins/auth.js.map +1 -1
- package/dist/plugins/headerSanitization.d.ts +15 -0
- package/dist/plugins/headerSanitization.d.ts.map +1 -0
- package/dist/plugins/headerSanitization.js +39 -0
- package/dist/plugins/headerSanitization.js.map +1 -0
- package/dist/plugins/machinePrincipal.d.ts +28 -0
- package/dist/plugins/machinePrincipal.d.ts.map +1 -0
- package/dist/plugins/machinePrincipal.js +45 -0
- package/dist/plugins/machinePrincipal.js.map +1 -0
- package/dist/plugins/mtls.d.ts +21 -2
- package/dist/plugins/mtls.d.ts.map +1 -1
- package/dist/plugins/mtls.js +94 -47
- package/dist/plugins/mtls.js.map +1 -1
- package/dist/plugins/rateLimit.d.ts +5 -4
- package/dist/plugins/rateLimit.d.ts.map +1 -1
- package/dist/plugins/rateLimit.js +11 -8
- package/dist/plugins/rateLimit.js.map +1 -1
- package/dist/repositories/application.d.ts +1 -1
- package/dist/repositories/application.d.ts.map +1 -1
- package/dist/repositories/application.js +8 -2
- package/dist/repositories/application.js.map +1 -1
- package/dist/repositories/session.d.ts +1 -0
- package/dist/repositories/session.d.ts.map +1 -1
- package/dist/repositories/types.d.ts +5 -1
- package/dist/repositories/types.d.ts.map +1 -1
- package/dist/routes/admin/organizations.d.ts.map +1 -1
- package/dist/routes/admin/organizations.js +31 -2
- package/dist/routes/admin/organizations.js.map +1 -1
- package/dist/routes/apiKeys.d.ts.map +1 -1
- package/dist/routes/apiKeys.js +23 -5
- package/dist/routes/apiKeys.js.map +1 -1
- package/dist/routes/federation.d.ts.map +1 -1
- package/dist/routes/federation.js +8 -2
- package/dist/routes/federation.js.map +1 -1
- package/dist/routes/oauth.d.ts.map +1 -1
- package/dist/routes/oauth.js +38 -2
- package/dist/routes/oauth.js.map +1 -1
- package/dist/routes/oauth2.d.ts.map +1 -1
- package/dist/routes/oauth2.js +92 -13
- package/dist/routes/oauth2.js.map +1 -1
- package/dist/routes/profile.js +2 -2
- package/dist/routes/profile.js.map +1 -1
- package/dist/routes/saml.d.ts +24 -0
- package/dist/routes/saml.d.ts.map +1 -1
- package/dist/routes/saml.js +32 -3
- package/dist/routes/saml.js.map +1 -1
- package/dist/routes/serviceAccounts.d.ts.map +1 -1
- package/dist/routes/serviceAccounts.js +78 -2
- package/dist/routes/serviceAccounts.js.map +1 -1
- package/dist/routes/sessions.js +3 -3
- package/dist/routes/sessions.js.map +1 -1
- package/dist/routes/smsOtp.d.ts.map +1 -1
- package/dist/routes/smsOtp.js +6 -0
- package/dist/routes/smsOtp.js.map +1 -1
- package/dist/routes/totp.d.ts.map +1 -1
- package/dist/routes/totp.js +24 -10
- package/dist/routes/totp.js.map +1 -1
- package/dist/routes/webauthn.d.ts.map +1 -1
- package/dist/routes/webauthn.js +8 -2
- package/dist/routes/webauthn.js.map +1 -1
- package/dist/sdk/index.d.ts.map +1 -1
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/types.d.ts +4 -1
- package/dist/sdk/types.d.ts.map +1 -1
- package/dist/services/application/organization.d.ts +5 -1
- package/dist/services/application/organization.d.ts.map +1 -1
- package/dist/services/application/organization.js.map +1 -1
- package/dist/services/connectors/google.d.ts +18 -1
- package/dist/services/connectors/google.d.ts.map +1 -1
- package/dist/services/connectors/google.js +25 -3
- package/dist/services/connectors/google.js.map +1 -1
- package/dist/services/connectors/oidc.d.ts +14 -2
- package/dist/services/connectors/oidc.d.ts.map +1 -1
- package/dist/services/connectors/oidc.js +29 -3
- package/dist/services/connectors/oidc.js.map +1 -1
- package/dist/services/connectors/types.d.ts +13 -1
- package/dist/services/connectors/types.d.ts.map +1 -1
- package/dist/services/domain/authentication.d.ts.map +1 -1
- package/dist/services/domain/authentication.js +36 -19
- package/dist/services/domain/authentication.js.map +1 -1
- package/dist/services/domain/organization.d.ts +5 -1
- package/dist/services/domain/organization.d.ts.map +1 -1
- package/dist/services/domain/organization.js.map +1 -1
- package/dist/services/events/types.d.ts +1 -1
- package/dist/services/events/types.d.ts.map +1 -1
- package/dist/services/events/validate.d.ts.map +1 -1
- package/dist/services/events/validate.js +6 -0
- package/dist/services/events/validate.js.map +1 -1
- package/dist/services/magicLinks.d.ts.map +1 -1
- package/dist/services/magicLinks.js +13 -9
- package/dist/services/magicLinks.js.map +1 -1
- package/dist/services/oauth2.d.ts +72 -2
- package/dist/services/oauth2.d.ts.map +1 -1
- package/dist/services/oauth2.js +106 -6
- package/dist/services/oauth2.js.map +1 -1
- package/dist/services/redirectUri.d.ts +56 -0
- package/dist/services/redirectUri.d.ts.map +1 -0
- package/dist/services/redirectUri.js +129 -0
- package/dist/services/redirectUri.js.map +1 -0
- package/dist/services/scopes.d.ts +113 -0
- package/dist/services/scopes.d.ts.map +1 -0
- package/dist/services/scopes.js +138 -0
- package/dist/services/scopes.js.map +1 -0
- package/dist/services/serviceAccounts.d.ts +20 -0
- package/dist/services/serviceAccounts.d.ts.map +1 -1
- package/dist/services/serviceAccounts.js +47 -1
- package/dist/services/serviceAccounts.js.map +1 -1
- package/dist/services/sessionRevocation.d.ts +76 -0
- package/dist/services/sessionRevocation.d.ts.map +1 -0
- package/dist/services/sessionRevocation.js +86 -0
- package/dist/services/sessionRevocation.js.map +1 -0
- package/dist/services/singleUse.d.ts +68 -0
- package/dist/services/singleUse.d.ts.map +1 -0
- package/dist/services/singleUse.js +54 -0
- package/dist/services/singleUse.js.map +1 -0
- package/dist/services/smsOtp.d.ts.map +1 -1
- package/dist/services/smsOtp.js +12 -8
- package/dist/services/smsOtp.js.map +1 -1
- package/dist/services/tokens.d.ts +2 -0
- package/dist/services/tokens.d.ts.map +1 -1
- package/dist/services/tokens.js +5 -0
- package/dist/services/tokens.js.map +1 -1
- package/dist/services/trustedProxies.d.ts +90 -0
- package/dist/services/trustedProxies.d.ts.map +1 -0
- package/dist/services/trustedProxies.js +283 -0
- package/dist/services/trustedProxies.js.map +1 -0
- package/dist/setup-server.js +2 -1
- package/dist/setup-server.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +4 -5
|
@@ -3,6 +3,7 @@ export declare function createServiceAccount(input: {
|
|
|
3
3
|
orgId: string;
|
|
4
4
|
name: string;
|
|
5
5
|
description?: string;
|
|
6
|
+
certFingerprint?: string | null;
|
|
6
7
|
}): Promise<ServiceAccount>;
|
|
7
8
|
export declare function findServiceAccountsByOrgId(orgId: string): Promise<ServiceAccount[]>;
|
|
8
9
|
export declare function findServiceAccountById(id: string, orgId: string): Promise<ServiceAccount | undefined>;
|
|
@@ -11,6 +12,25 @@ export declare function updateServiceAccount(id: string, orgId: string, updates:
|
|
|
11
12
|
description: string;
|
|
12
13
|
isActive: boolean;
|
|
13
14
|
}>): Promise<ServiceAccount | undefined>;
|
|
15
|
+
/**
|
|
16
|
+
* Bind or clear the client certificate this account authenticates with.
|
|
17
|
+
*
|
|
18
|
+
* Clearing sets the column to null, which removes certificate authentication
|
|
19
|
+
* for the account entirely — an unbound account can only use an API key. The
|
|
20
|
+
* unique index on `cert_fingerprint` is what stops one certificate being bound
|
|
21
|
+
* to two accounts; a conflict surfaces as an error here rather than silently
|
|
22
|
+
* picking a winner.
|
|
23
|
+
*
|
|
24
|
+
* @throws if `fingerprint` is not a well-formed SHA-256 digest, or if the
|
|
25
|
+
* certificate is already bound to a different account.
|
|
26
|
+
*/
|
|
27
|
+
export declare function setServiceAccountCertificate(id: string, orgId: string, fingerprint: string | null): Promise<ServiceAccount | undefined>;
|
|
28
|
+
/**
|
|
29
|
+
* Permanently stop an account authenticating. Kept separate from
|
|
30
|
+
* `isActive: false` so a later reactivation cannot silently restore access —
|
|
31
|
+
* reactivation requires clearing `revokedAt` deliberately.
|
|
32
|
+
*/
|
|
33
|
+
export declare function revokeServiceAccount(id: string, orgId: string): Promise<ServiceAccount | undefined>;
|
|
14
34
|
export declare function listServiceAccountApiKeys(serviceAccountId: string): Promise<{
|
|
15
35
|
id: string;
|
|
16
36
|
name: string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serviceAccounts.d.ts","sourceRoot":"","sources":["../../src/services/serviceAccounts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"serviceAccounts.d.ts","sourceRoot":"","sources":["../../src/services/serviceAccounts.ts"],"names":[],"mappings":"AAGA,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEhF,wBAAsB,oBAAoB,CAAC,KAAK,EAAE;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,GAAG,OAAO,CAAC,cAAc,CAAC,CAW1B;AAED,wBAAsB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAMzF;AAED,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAarC;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,GACzE,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAOrC;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,4BAA4B,CAChD,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAAG,IAAI,GACzB,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAmBrC;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAOrC;AAED,wBAAsB,yBAAyB,CAAC,gBAAgB,EAAE,MAAM;;;;;;;;;KAcvE"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { eq, and, sql } from "drizzle-orm";
|
|
1
|
+
import { eq, and, isNull, sql } from "drizzle-orm";
|
|
2
|
+
import { canonicalFingerprint, isValidFingerprint } from "./trustedProxies.js";
|
|
2
3
|
import { db } from "../db/index.js";
|
|
3
4
|
import { serviceAccounts, apiKeys } from "../db/schema.js";
|
|
4
5
|
export async function createServiceAccount(input) {
|
|
@@ -8,6 +9,7 @@ export async function createServiceAccount(input) {
|
|
|
8
9
|
orgId: input.orgId,
|
|
9
10
|
name: input.name,
|
|
10
11
|
description: input.description ?? null,
|
|
12
|
+
certFingerprint: input.certFingerprint ?? null,
|
|
11
13
|
})
|
|
12
14
|
.returning();
|
|
13
15
|
return record;
|
|
@@ -35,6 +37,50 @@ export async function updateServiceAccount(id, orgId, updates) {
|
|
|
35
37
|
.returning();
|
|
36
38
|
return updated;
|
|
37
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Bind or clear the client certificate this account authenticates with.
|
|
42
|
+
*
|
|
43
|
+
* Clearing sets the column to null, which removes certificate authentication
|
|
44
|
+
* for the account entirely — an unbound account can only use an API key. The
|
|
45
|
+
* unique index on `cert_fingerprint` is what stops one certificate being bound
|
|
46
|
+
* to two accounts; a conflict surfaces as an error here rather than silently
|
|
47
|
+
* picking a winner.
|
|
48
|
+
*
|
|
49
|
+
* @throws if `fingerprint` is not a well-formed SHA-256 digest, or if the
|
|
50
|
+
* certificate is already bound to a different account.
|
|
51
|
+
*/
|
|
52
|
+
export async function setServiceAccountCertificate(id, orgId, fingerprint) {
|
|
53
|
+
// Canonicalize here rather than trusting the caller. The hex and
|
|
54
|
+
// colon-separated spellings of one certificate must not become two bindings,
|
|
55
|
+
// and this is the only place every caller is guaranteed to pass through.
|
|
56
|
+
let canonical = null;
|
|
57
|
+
if (fingerprint !== null) {
|
|
58
|
+
const trimmed = fingerprint.trim();
|
|
59
|
+
if (!isValidFingerprint(trimmed)) {
|
|
60
|
+
throw new Error("fingerprint must be a SHA-256 digest (64 hex characters)");
|
|
61
|
+
}
|
|
62
|
+
canonical = canonicalFingerprint(trimmed);
|
|
63
|
+
}
|
|
64
|
+
const [updated] = await db
|
|
65
|
+
.update(serviceAccounts)
|
|
66
|
+
.set({ certFingerprint: canonical, updatedAt: sql `now()` })
|
|
67
|
+
.where(and(eq(serviceAccounts.id, id), eq(serviceAccounts.orgId, orgId)))
|
|
68
|
+
.returning();
|
|
69
|
+
return updated;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Permanently stop an account authenticating. Kept separate from
|
|
73
|
+
* `isActive: false` so a later reactivation cannot silently restore access —
|
|
74
|
+
* reactivation requires clearing `revokedAt` deliberately.
|
|
75
|
+
*/
|
|
76
|
+
export async function revokeServiceAccount(id, orgId) {
|
|
77
|
+
const [updated] = await db
|
|
78
|
+
.update(serviceAccounts)
|
|
79
|
+
.set({ isActive: false, revokedAt: sql `now()`, updatedAt: sql `now()` })
|
|
80
|
+
.where(and(eq(serviceAccounts.id, id), eq(serviceAccounts.orgId, orgId), isNull(serviceAccounts.revokedAt)))
|
|
81
|
+
.returning();
|
|
82
|
+
return updated;
|
|
83
|
+
}
|
|
38
84
|
export async function listServiceAccountApiKeys(serviceAccountId) {
|
|
39
85
|
return db
|
|
40
86
|
.select({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serviceAccounts.js","sourceRoot":"","sources":["../../src/services/serviceAccounts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"serviceAccounts.js","sourceRoot":"","sources":["../../src/services/serviceAccounts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized credential revocation.
|
|
3
|
+
*
|
|
4
|
+
* Every "this account should stop being logged in" operation routes through
|
|
5
|
+
* here. Before this existed, revocation was open-coded per call site, and the
|
|
6
|
+
* most important call site was missing entirely: completing a password reset
|
|
7
|
+
* changed the password and left every existing session and refresh token
|
|
8
|
+
* working. That defeats the purpose of a reset, which is the standard response
|
|
9
|
+
* to a suspected compromise — the intruder keeps their session.
|
|
10
|
+
*
|
|
11
|
+
* The primitives below are deliberately separate so a caller can be precise
|
|
12
|
+
* about what it invalidates, and so the composite operations are visibly
|
|
13
|
+
* composed rather than reimplemented at each site.
|
|
14
|
+
*/
|
|
15
|
+
export interface RevocationCounts {
|
|
16
|
+
refreshTokens: number;
|
|
17
|
+
sessions: number;
|
|
18
|
+
recoveryCredentials: number;
|
|
19
|
+
}
|
|
20
|
+
export interface RevokeOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Keep this session and its refresh token alive, for a change the user is
|
|
23
|
+
* making to their own account.
|
|
24
|
+
*
|
|
25
|
+
* Never pass it on a reset the user did not initiate themselves: the current
|
|
26
|
+
* session is precisely what an attacker would be holding, and preserving it
|
|
27
|
+
* would leave them in.
|
|
28
|
+
*/
|
|
29
|
+
exceptSessionId?: string;
|
|
30
|
+
/** Keep this refresh token alive, for the same reason. */
|
|
31
|
+
exceptRefreshTokenId?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Revoke the user's refresh tokens, so no further access token can be minted
|
|
35
|
+
* from an existing session.
|
|
36
|
+
*/
|
|
37
|
+
export declare function revokeRefreshTokens(userId: string, options?: RevokeOptions): Promise<number>;
|
|
38
|
+
/**
|
|
39
|
+
* Revoke the user's authentication sessions.
|
|
40
|
+
*
|
|
41
|
+
* A revoked session stops authorising requests immediately; it is not merely
|
|
42
|
+
* hidden from a session list.
|
|
43
|
+
*/
|
|
44
|
+
export declare function revokeAuthenticationSessions(userId: string, options?: RevokeOptions): Promise<number>;
|
|
45
|
+
/**
|
|
46
|
+
* Revoke outstanding recovery credentials.
|
|
47
|
+
*
|
|
48
|
+
* A reset token already sitting in someone's inbox stays valid until it
|
|
49
|
+
* expires unless it is spent here. Someone who intercepted an earlier reset
|
|
50
|
+
* email could otherwise complete it after the user had already recovered.
|
|
51
|
+
*/
|
|
52
|
+
export declare function revokeRecoveryCredentials(userId: string): Promise<number>;
|
|
53
|
+
/**
|
|
54
|
+
* Log the user out everywhere: sessions and refresh tokens together.
|
|
55
|
+
*
|
|
56
|
+
* This is what most credential changes want. Revoking only one leaves a live
|
|
57
|
+
* credential behind: a session with no refresh token still authorises requests
|
|
58
|
+
* until it expires, and a refresh token with no session can still mint access
|
|
59
|
+
* tokens.
|
|
60
|
+
*/
|
|
61
|
+
export declare function revokeUserSessions(userId: string, options?: RevokeOptions): Promise<RevocationCounts>;
|
|
62
|
+
/**
|
|
63
|
+
* Everything: sessions, refresh tokens, and outstanding recovery credentials.
|
|
64
|
+
*
|
|
65
|
+
* Used after a password reset.
|
|
66
|
+
*
|
|
67
|
+
* API keys are deliberately **not** revoked. They are separately issued,
|
|
68
|
+
* long-lived credentials belonging to integrations rather than to the person,
|
|
69
|
+
* and silently killing them on a password reset breaks deployments without
|
|
70
|
+
* improving the account's own security. The residual gap is real — an API key
|
|
71
|
+
* minted by an attacker who already held the password survives — and the right
|
|
72
|
+
* answer is key expiry and rotation rather than coupling key lifetime to a
|
|
73
|
+
* human's password.
|
|
74
|
+
*/
|
|
75
|
+
export declare function revokeAllUserCredentials(userId: string, options?: RevokeOptions): Promise<RevocationCounts>;
|
|
76
|
+
//# sourceMappingURL=sessionRevocation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionRevocation.d.ts","sourceRoot":"","sources":["../../src/services/sessionRevocation.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0DAA0D;IAC1D,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAID;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED;;;;;GAKG;AACH,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO/E;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,gBAAgB,CAAC,CAI3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,gBAAgB,CAAC,CAK3B"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { and, eq, isNull, ne } from "drizzle-orm";
|
|
2
|
+
import { db } from "../db/index.js";
|
|
3
|
+
import { passwordResetTokens, refreshTokens, userSessions } from "../db/schema.js";
|
|
4
|
+
const EMPTY = { refreshTokens: 0, sessions: 0, recoveryCredentials: 0 };
|
|
5
|
+
/**
|
|
6
|
+
* Revoke the user's refresh tokens, so no further access token can be minted
|
|
7
|
+
* from an existing session.
|
|
8
|
+
*/
|
|
9
|
+
export async function revokeRefreshTokens(userId, options = {}) {
|
|
10
|
+
const conditions = [eq(refreshTokens.userId, userId), isNull(refreshTokens.revokedAt)];
|
|
11
|
+
if (options.exceptRefreshTokenId) {
|
|
12
|
+
conditions.push(ne(refreshTokens.id, options.exceptRefreshTokenId));
|
|
13
|
+
}
|
|
14
|
+
const rows = await db
|
|
15
|
+
.update(refreshTokens)
|
|
16
|
+
.set({ revokedAt: new Date() })
|
|
17
|
+
.where(and(...conditions))
|
|
18
|
+
.returning({ id: refreshTokens.id });
|
|
19
|
+
return rows.length;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Revoke the user's authentication sessions.
|
|
23
|
+
*
|
|
24
|
+
* A revoked session stops authorising requests immediately; it is not merely
|
|
25
|
+
* hidden from a session list.
|
|
26
|
+
*/
|
|
27
|
+
export async function revokeAuthenticationSessions(userId, options = {}) {
|
|
28
|
+
const conditions = [eq(userSessions.userId, userId), isNull(userSessions.revokedAt)];
|
|
29
|
+
if (options.exceptSessionId) {
|
|
30
|
+
conditions.push(ne(userSessions.id, options.exceptSessionId));
|
|
31
|
+
}
|
|
32
|
+
const rows = await db
|
|
33
|
+
.update(userSessions)
|
|
34
|
+
.set({ revokedAt: new Date() })
|
|
35
|
+
.where(and(...conditions))
|
|
36
|
+
.returning({ id: userSessions.id });
|
|
37
|
+
return rows.length;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Revoke outstanding recovery credentials.
|
|
41
|
+
*
|
|
42
|
+
* A reset token already sitting in someone's inbox stays valid until it
|
|
43
|
+
* expires unless it is spent here. Someone who intercepted an earlier reset
|
|
44
|
+
* email could otherwise complete it after the user had already recovered.
|
|
45
|
+
*/
|
|
46
|
+
export async function revokeRecoveryCredentials(userId) {
|
|
47
|
+
const rows = await db
|
|
48
|
+
.update(passwordResetTokens)
|
|
49
|
+
.set({ usedAt: new Date() })
|
|
50
|
+
.where(and(eq(passwordResetTokens.userId, userId), isNull(passwordResetTokens.usedAt)))
|
|
51
|
+
.returning({ id: passwordResetTokens.id });
|
|
52
|
+
return rows.length;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Log the user out everywhere: sessions and refresh tokens together.
|
|
56
|
+
*
|
|
57
|
+
* This is what most credential changes want. Revoking only one leaves a live
|
|
58
|
+
* credential behind: a session with no refresh token still authorises requests
|
|
59
|
+
* until it expires, and a refresh token with no session can still mint access
|
|
60
|
+
* tokens.
|
|
61
|
+
*/
|
|
62
|
+
export async function revokeUserSessions(userId, options = {}) {
|
|
63
|
+
const sessions = await revokeAuthenticationSessions(userId, options);
|
|
64
|
+
const refreshTokensRevoked = await revokeRefreshTokens(userId, options);
|
|
65
|
+
return { ...EMPTY, sessions, refreshTokens: refreshTokensRevoked };
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Everything: sessions, refresh tokens, and outstanding recovery credentials.
|
|
69
|
+
*
|
|
70
|
+
* Used after a password reset.
|
|
71
|
+
*
|
|
72
|
+
* API keys are deliberately **not** revoked. They are separately issued,
|
|
73
|
+
* long-lived credentials belonging to integrations rather than to the person,
|
|
74
|
+
* and silently killing them on a password reset breaks deployments without
|
|
75
|
+
* improving the account's own security. The residual gap is real — an API key
|
|
76
|
+
* minted by an attacker who already held the password survives — and the right
|
|
77
|
+
* answer is key expiry and rotation rather than coupling key lifetime to a
|
|
78
|
+
* human's password.
|
|
79
|
+
*/
|
|
80
|
+
export async function revokeAllUserCredentials(userId, options = {}) {
|
|
81
|
+
const sessions = await revokeAuthenticationSessions(userId, options);
|
|
82
|
+
const refreshTokensRevoked = await revokeRefreshTokens(userId, options);
|
|
83
|
+
const recoveryCredentials = await revokeRecoveryCredentials(userId);
|
|
84
|
+
return { sessions, refreshTokens: refreshTokensRevoked, recoveryCredentials };
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=sessionRevocation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionRevocation.js","sourceRoot":"","sources":["../../src/services/sessionRevocation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { magicLinks, passwordResetTokens, smsOtpCodes } from "../db/schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* Atomic consumption of single-use credentials.
|
|
4
|
+
*
|
|
5
|
+
* A single-use credential has one dangerous shape, and it is always the same:
|
|
6
|
+
*
|
|
7
|
+
* ```text
|
|
8
|
+
* SELECT ... WHERE used_at IS NULL <- conditional
|
|
9
|
+
* if (!row) return
|
|
10
|
+
* UPDATE ... SET used_at = now() <- UNCONDITIONAL: the race
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Between the SELECT and the UPDATE, any number of concurrent requests can pass
|
|
14
|
+
* the same check. A magic link redeemed by ten parallel requests logs in ten
|
|
15
|
+
* times; a password reset token spent ten times over writes ten different
|
|
16
|
+
* passwords, last writer winning.
|
|
17
|
+
*
|
|
18
|
+
* The fix is to make the write itself the gate:
|
|
19
|
+
*
|
|
20
|
+
* ```text
|
|
21
|
+
* UPDATE ... SET used_at = now()
|
|
22
|
+
* WHERE token_hash = ? AND expires_at > now() AND used_at IS NULL
|
|
23
|
+
* RETURNING ...
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* PostgreSQL evaluates that predicate while holding a row lock, so exactly one
|
|
27
|
+
* transaction can update the row and see a returned row. Everyone else matches
|
|
28
|
+
* zero rows. The claim and the validation are one statement, so there is no
|
|
29
|
+
* window between them to lose.
|
|
30
|
+
*
|
|
31
|
+
* All consumption goes through here so the pattern exists once. A credential
|
|
32
|
+
* that consumes its own token inline is a credential that can be raced.
|
|
33
|
+
*/
|
|
34
|
+
export type ConsumeOutcome =
|
|
35
|
+
/** This caller claimed the credential. */
|
|
36
|
+
"consumed"
|
|
37
|
+
/** A row exists but was already spent. Somebody replayed it. */
|
|
38
|
+
| "replayed"
|
|
39
|
+
/** A row exists but has passed its expiry. */
|
|
40
|
+
| "expired"
|
|
41
|
+
/** No row for this value. */
|
|
42
|
+
| "not_found";
|
|
43
|
+
export interface ConsumeResult<T> {
|
|
44
|
+
outcome: ConsumeOutcome;
|
|
45
|
+
/** Present only when `outcome` is `consumed`. */
|
|
46
|
+
record?: T;
|
|
47
|
+
/**
|
|
48
|
+
* Why the credential was refused. Set for `replayed` and `expired`; omitted
|
|
49
|
+
* for `not_found`, so a caller cannot distinguish "never existed" from
|
|
50
|
+
* "deleted", which is itself information.
|
|
51
|
+
*/
|
|
52
|
+
reason?: "replayed" | "expired";
|
|
53
|
+
}
|
|
54
|
+
export type MagicLinkRow = typeof magicLinks.$inferSelect;
|
|
55
|
+
export type PasswordResetTokenRow = typeof passwordResetTokens.$inferSelect;
|
|
56
|
+
export type SmsOtpCodeRow = typeof smsOtpCodes.$inferSelect;
|
|
57
|
+
/** Atomically consume a magic link. */
|
|
58
|
+
export declare function consumeMagicLinkRow(tokenHash: string, now: Date): Promise<ConsumeResult<MagicLinkRow>>;
|
|
59
|
+
/** Atomically consume a password reset token. */
|
|
60
|
+
export declare function consumePasswordResetTokenRow(tokenHash: string, now: Date): Promise<ConsumeResult<PasswordResetTokenRow>>;
|
|
61
|
+
/**
|
|
62
|
+
* Atomically consume an SMS OTP code.
|
|
63
|
+
*
|
|
64
|
+
* Scoped to the user as well as the code. A code is six digits, so a lookup on
|
|
65
|
+
* the hash alone could let one user's code be spent against another's row.
|
|
66
|
+
*/
|
|
67
|
+
export declare function consumeSmsOtpCodeRow(userId: string, codeHash: string, now: Date): Promise<ConsumeResult<SmsOtpCodeRow>>;
|
|
68
|
+
//# sourceMappingURL=singleUse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"singleUse.d.ts","sourceRoot":"","sources":["../../src/services/singleUse.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,MAAM,MAAM,cAAc;AACxB,0CAA0C;AACxC,UAAU;AACZ,gEAAgE;GAC9D,UAAU;AACZ,8CAA8C;GAC5C,SAAS;AACX,6BAA6B;GAC3B,WAAW,CAAC;AAEhB,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,OAAO,EAAE,cAAc,CAAC;IACxB,iDAAiD;IACjD,MAAM,CAAC,EAAE,CAAC,CAAC;IACX;;;;OAIG;IACH,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CACjC;AAuED,MAAM,MAAM,YAAY,GAAG,OAAO,UAAU,CAAC,YAAY,CAAC;AAC1D,MAAM,MAAM,qBAAqB,GAAG,OAAO,mBAAmB,CAAC,YAAY,CAAC;AAC5E,MAAM,MAAM,aAAa,GAAG,OAAO,WAAW,CAAC,YAAY,CAAC;AAE5D,uCAAuC;AACvC,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,IAAI,GACR,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAEtC;AAED,iDAAiD;AACjD,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,IAAI,GACR,OAAO,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC,CAO/C;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,IAAI,GACR,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAQvC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { and, eq, gt, isNull } from "drizzle-orm";
|
|
2
|
+
import { db } from "../db/index.js";
|
|
3
|
+
import { magicLinks, passwordResetTokens, smsOtpCodes } from "../db/schema.js";
|
|
4
|
+
async function claimAndClassify(table, hashColumn, hashValue, now, extra) {
|
|
5
|
+
const predicate = and(eq(hashColumn, hashValue), gt(table.expiresAt, now), isNull(table.usedAt), extra);
|
|
6
|
+
const claimed = (await db
|
|
7
|
+
.update(table)
|
|
8
|
+
.set({ usedAt: now })
|
|
9
|
+
.where(predicate)
|
|
10
|
+
.returning());
|
|
11
|
+
if (claimed.length === 1) {
|
|
12
|
+
return { outcome: "consumed", record: claimed[0] };
|
|
13
|
+
}
|
|
14
|
+
if (claimed.length > 1) {
|
|
15
|
+
// The hash column is not unique, so "single use" cannot mean anything.
|
|
16
|
+
throw new Error(`atomic claim matched ${claimed.length} rows; the hash column must be unique`);
|
|
17
|
+
}
|
|
18
|
+
// Why could we not claim it? Only worth distinguishing a replay, because that
|
|
19
|
+
// means the credential leaked and somebody came back with it.
|
|
20
|
+
const [existing] = (await db
|
|
21
|
+
.select()
|
|
22
|
+
.from(table)
|
|
23
|
+
.where(and(eq(hashColumn, hashValue), extra))
|
|
24
|
+
.limit(1));
|
|
25
|
+
if (!existing)
|
|
26
|
+
return { outcome: "not_found" };
|
|
27
|
+
if (existing.usedAt)
|
|
28
|
+
return { outcome: "replayed", reason: "replayed" };
|
|
29
|
+
if (existing.expiresAt.getTime() <= now.getTime()) {
|
|
30
|
+
return { outcome: "expired", reason: "expired" };
|
|
31
|
+
}
|
|
32
|
+
// Present, unused, and unexpired, yet the claim matched nothing: another
|
|
33
|
+
// transaction won the race between the two statements. From here that is a
|
|
34
|
+
// replay.
|
|
35
|
+
return { outcome: "replayed", reason: "replayed" };
|
|
36
|
+
}
|
|
37
|
+
/** Atomically consume a magic link. */
|
|
38
|
+
export function consumeMagicLinkRow(tokenHash, now) {
|
|
39
|
+
return claimAndClassify(magicLinks, magicLinks.tokenHash, tokenHash, now);
|
|
40
|
+
}
|
|
41
|
+
/** Atomically consume a password reset token. */
|
|
42
|
+
export function consumePasswordResetTokenRow(tokenHash, now) {
|
|
43
|
+
return claimAndClassify(passwordResetTokens, passwordResetTokens.tokenHash, tokenHash, now);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Atomically consume an SMS OTP code.
|
|
47
|
+
*
|
|
48
|
+
* Scoped to the user as well as the code. A code is six digits, so a lookup on
|
|
49
|
+
* the hash alone could let one user's code be spent against another's row.
|
|
50
|
+
*/
|
|
51
|
+
export function consumeSmsOtpCodeRow(userId, codeHash, now) {
|
|
52
|
+
return claimAndClassify(smsOtpCodes, smsOtpCodes.codeHash, codeHash, now, eq(smsOtpCodes.userId, userId));
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=singleUse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"singleUse.js","sourceRoot":"","sources":["../../src/services/singleUse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAY,MAAM,aAAa,CAAC;AAE5D,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AA4E/E,KAAK,UAAU,gBAAgB,CAC7B,KAAqB,EACrB,UAAoB,EACpB,SAAiB,EACjB,GAAS,EACT,KAAW;IAEX,MAAM,SAAS,GAAG,GAAG,CACnB,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,EACzB,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,GAAG,CAAC,EACxB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EACpB,KAAK,CACN,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE;SACtB,MAAM,CAAC,KAAK,CAAC;SACb,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;SACpB,KAAK,CAAC,SAAS,CAAC;SAChB,SAAS,EAAE,CAAQ,CAAC;IAEvB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACrD,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,uEAAuE;QACvE,MAAM,IAAI,KAAK,CACb,wBAAwB,OAAO,CAAC,MAAM,uCAAuC,CAC9E,CAAC;IACJ,CAAC;IAED,8EAA8E;IAC9E,8DAA8D;IAC9D,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE;SACzB,MAAM,EAAE;SACR,IAAI,CAAC,KAAK,CAAC;SACX,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC;SAC5C,KAAK,CAAC,CAAC,CAAC,CAAQ,CAAC;IAEpB,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAC/C,IAAI,QAAQ,CAAC,MAAM;QAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IACxE,IAAI,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;QAClD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IACnD,CAAC;IAED,yEAAyE;IACzE,2EAA2E;IAC3E,UAAU;IACV,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AACrD,CAAC;AAMD,uCAAuC;AACvC,MAAM,UAAU,mBAAmB,CACjC,SAAiB,EACjB,GAAS;IAET,OAAO,gBAAgB,CAAe,UAAU,EAAE,UAAU,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;AAC1F,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,4BAA4B,CAC1C,SAAiB,EACjB,GAAS;IAET,OAAO,gBAAgB,CACrB,mBAAmB,EACnB,mBAAmB,CAAC,SAAS,EAC7B,SAAS,EACT,GAAG,CACJ,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAc,EACd,QAAgB,EAChB,GAAS;IAET,OAAO,gBAAgB,CACrB,WAAW,EACX,WAAW,CAAC,QAAQ,EACpB,QAAQ,EACR,GAAG,EACH,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAC/B,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smsOtp.d.ts","sourceRoot":"","sources":["../../src/services/smsOtp.ts"],"names":[],"mappings":"AAGA,OAAO,EAAsB,KAAK,IAAI,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"smsOtp.d.ts","sourceRoot":"","sources":["../../src/services/smsOtp.ts"],"names":[],"mappings":"AAGA,OAAO,EAAsB,KAAK,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAQhE,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAMD,wBAAsB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBjF;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAejF;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOvE;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK1F"}
|
package/dist/services/smsOtp.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
|
-
import { eq
|
|
2
|
+
import { eq } from "drizzle-orm";
|
|
3
3
|
import { db } from "../db/index.js";
|
|
4
4
|
import { smsOtpCodes, users } from "../db/schema.js";
|
|
5
5
|
import { smsProvider } from "./sms.js";
|
|
6
|
+
import { consumeSmsOtpCodeRow } from "./singleUse.js";
|
|
7
|
+
import { emit } from "./events/bus.js";
|
|
6
8
|
const CODE_TTL_SECONDS = 300;
|
|
7
9
|
const CODE_LENGTH = 6;
|
|
8
10
|
export function generateSmsCode() {
|
|
@@ -29,14 +31,16 @@ export async function sendSmsOtp(user, phoneNumber) {
|
|
|
29
31
|
export async function verifySmsOtp(userId, code) {
|
|
30
32
|
const codeHash = hashCode(code);
|
|
31
33
|
const now = new Date();
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
// Claim atomically, so a code cannot be spent by two parallel verifications.
|
|
35
|
+
// Scoped to the user as well as the hash: a six-digit code is short enough
|
|
36
|
+
// that a global lookup could collide across accounts.
|
|
37
|
+
const result = await consumeSmsOtpCodeRow(userId, codeHash, now);
|
|
38
|
+
if (result.outcome !== "consumed") {
|
|
39
|
+
if (result.reason === "replayed") {
|
|
40
|
+
emit({ type: "sms_otp_replayed", payload: { userId } });
|
|
41
|
+
}
|
|
38
42
|
return false;
|
|
39
|
-
|
|
43
|
+
}
|
|
40
44
|
return true;
|
|
41
45
|
}
|
|
42
46
|
export async function hasVerifiedPhone(userId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smsOtp.js","sourceRoot":"","sources":["../../src/services/smsOtp.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"smsOtp.js","sourceRoot":"","sources":["../../src/services/smsOtp.ts"],"names":[],"mappings":"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"}
|
|
@@ -66,6 +66,8 @@ export interface AccessTokenOptions {
|
|
|
66
66
|
deviceFingerprint?: string;
|
|
67
67
|
/** Proof that the MFA requirement for this user was satisfied. */
|
|
68
68
|
mfaFactor?: MfaAssertion;
|
|
69
|
+
/** Scopes granted at the authorization step, carried on the refresh token. */
|
|
70
|
+
scopes?: string[];
|
|
69
71
|
}
|
|
70
72
|
export declare function createAccessToken(user: User, opts?: AccessTokenOptions): Promise<string>;
|
|
71
73
|
export interface ApplicationAccessTokenOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/services/tokens.ts"],"names":[],"mappings":"AAWA,OAAO,EAKL,KAAK,IAAI,EACT,KAAK,WAAW,EACjB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAa/C,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAerD;AAED;;;GAGG;AACH,wBAAsB,YAAY,gCAGjC;AAED;;;GAGG;AACH,wBAAsB,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GASlC;AAMD;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,CAAC;AAE3E;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAG,cAAc,CAAU;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,YAAY,MAAM,EAAE,MAAM,EAIzB;CACF;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,SAAS,CAAC,EAAE,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/services/tokens.ts"],"names":[],"mappings":"AAWA,OAAO,EAKL,KAAK,IAAI,EACT,KAAK,WAAW,EACjB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAa/C,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAerD;AAED;;;GAGG;AACH,wBAAsB,YAAY,gCAGjC;AAED;;;GAGG;AACH,wBAAsB,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GASlC;AAMD;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,CAAC;AAE3E;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAG,cAAc,CAAU;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,YAAY,MAAM,EAAE,MAAM,EAIzB;CACF;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,GAAE,kBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6B5F;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,6BAA6B,GAClC,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,WAAW,EAChB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,EACV,EAAE,CAAC,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAClB,IAAI,GAAE,kBAAuB,EAC7B,iBAAiB,CAAC,EAAE,MAAM,GACzB,OAAO,CAAC,QAAQ,CAAC,CAiCnB;AAED,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAgB3E;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,EAAE,CAAC,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAmF1B;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrE;AAED,wBAAsB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9E;AAOD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/services/tokens.js
CHANGED
|
@@ -157,6 +157,7 @@ export async function createTokenSet(user, ip, userAgent, opts = {}, deviceFinge
|
|
|
157
157
|
userAgent: userAgent ?? null,
|
|
158
158
|
deviceFingerprint: deviceFingerprint ?? null,
|
|
159
159
|
mfaFactor: opts.mfaFactor ?? null,
|
|
160
|
+
scopes: opts.scopes ?? [],
|
|
160
161
|
}).returning();
|
|
161
162
|
try {
|
|
162
163
|
const sessions = new SessionRepository();
|
|
@@ -246,6 +247,10 @@ export async function rotateRefreshToken(token, ip, userAgent, clientId, expecte
|
|
|
246
247
|
orgId,
|
|
247
248
|
clientId,
|
|
248
249
|
deviceFingerprint: claimed.deviceFingerprint ?? undefined,
|
|
250
|
+
// Carried forward from the token being rotated. A refresh may narrow the
|
|
251
|
+
// grant but never widen it, so the stored set is authoritative rather than
|
|
252
|
+
// anything the caller supplies.
|
|
253
|
+
...(claimed.scopes?.length ? { scopes: claimed.scopes } : {}),
|
|
249
254
|
...(claimed.mfaFactor
|
|
250
255
|
? { mfaFactor: claimed.mfaFactor }
|
|
251
256
|
: {}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/services/tokens.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/services/tokens.ts"],"names":[],"mappings":"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"}
|