@byline/admin 0.9.3
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/LICENSE +373 -0
- package/README.md +19 -0
- package/dist/abilities.d.ts +22 -0
- package/dist/abilities.d.ts.map +1 -0
- package/dist/abilities.js +29 -0
- package/dist/abilities.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/assert-admin-actor.d.ts +58 -0
- package/dist/lib/assert-admin-actor.d.ts.map +1 -0
- package/dist/lib/assert-admin-actor.js +82 -0
- package/dist/lib/assert-admin-actor.js.map +1 -0
- package/dist/modules/admin-account/commands.d.ts +30 -0
- package/dist/modules/admin-account/commands.d.ts.map +1 -0
- package/dist/modules/admin-account/commands.js +36 -0
- package/dist/modules/admin-account/commands.js.map +1 -0
- package/dist/modules/admin-account/errors.d.ts +52 -0
- package/dist/modules/admin-account/errors.d.ts.map +1 -0
- package/dist/modules/admin-account/errors.js +52 -0
- package/dist/modules/admin-account/errors.js.map +1 -0
- package/dist/modules/admin-account/index.d.ts +37 -0
- package/dist/modules/admin-account/index.d.ts.map +1 -0
- package/dist/modules/admin-account/index.js +35 -0
- package/dist/modules/admin-account/index.js.map +1 -0
- package/dist/modules/admin-account/schemas.d.ts +31 -0
- package/dist/modules/admin-account/schemas.d.ts.map +1 -0
- package/dist/modules/admin-account/schemas.js +69 -0
- package/dist/modules/admin-account/schemas.js.map +1 -0
- package/dist/modules/admin-account/service.d.ts +44 -0
- package/dist/modules/admin-account/service.d.ts.map +1 -0
- package/dist/modules/admin-account/service.js +76 -0
- package/dist/modules/admin-account/service.js.map +1 -0
- package/dist/modules/admin-permissions/abilities.d.ts +27 -0
- package/dist/modules/admin-permissions/abilities.d.ts.map +1 -0
- package/dist/modules/admin-permissions/abilities.js +40 -0
- package/dist/modules/admin-permissions/abilities.js.map +1 -0
- package/dist/modules/admin-permissions/commands.d.ts +30 -0
- package/dist/modules/admin-permissions/commands.d.ts.map +1 -0
- package/dist/modules/admin-permissions/commands.js +39 -0
- package/dist/modules/admin-permissions/commands.js.map +1 -0
- package/dist/modules/admin-permissions/dto.d.ts +18 -0
- package/dist/modules/admin-permissions/dto.d.ts.map +1 -0
- package/dist/modules/admin-permissions/dto.js +24 -0
- package/dist/modules/admin-permissions/dto.js.map +1 -0
- package/dist/modules/admin-permissions/errors.d.ts +34 -0
- package/dist/modules/admin-permissions/errors.d.ts.map +1 -0
- package/dist/modules/admin-permissions/errors.js +34 -0
- package/dist/modules/admin-permissions/errors.js.map +1 -0
- package/dist/modules/admin-permissions/index.d.ts +30 -0
- package/dist/modules/admin-permissions/index.d.ts.map +1 -0
- package/dist/modules/admin-permissions/index.js +27 -0
- package/dist/modules/admin-permissions/index.js.map +1 -0
- package/dist/modules/admin-permissions/repository.d.ts +48 -0
- package/dist/modules/admin-permissions/repository.d.ts.map +1 -0
- package/dist/modules/admin-permissions/repository.js +9 -0
- package/dist/modules/admin-permissions/repository.js.map +1 -0
- package/dist/modules/admin-permissions/schemas.d.ts +137 -0
- package/dist/modules/admin-permissions/schemas.d.ts.map +1 -0
- package/dist/modules/admin-permissions/schemas.js +99 -0
- package/dist/modules/admin-permissions/schemas.js.map +1 -0
- package/dist/modules/admin-permissions/service.d.ts +42 -0
- package/dist/modules/admin-permissions/service.d.ts.map +1 -0
- package/dist/modules/admin-permissions/service.js +114 -0
- package/dist/modules/admin-permissions/service.js.map +1 -0
- package/dist/modules/admin-roles/abilities.d.ts +33 -0
- package/dist/modules/admin-roles/abilities.d.ts.map +1 -0
- package/dist/modules/admin-roles/abilities.js +56 -0
- package/dist/modules/admin-roles/abilities.js.map +1 -0
- package/dist/modules/admin-roles/commands.d.ts +37 -0
- package/dist/modules/admin-roles/commands.d.ts.map +1 -0
- package/dist/modules/admin-roles/commands.js +70 -0
- package/dist/modules/admin-roles/commands.js.map +1 -0
- package/dist/modules/admin-roles/dto.d.ts +18 -0
- package/dist/modules/admin-roles/dto.d.ts.map +1 -0
- package/dist/modules/admin-roles/dto.js +27 -0
- package/dist/modules/admin-roles/dto.js.map +1 -0
- package/dist/modules/admin-roles/errors.d.ts +49 -0
- package/dist/modules/admin-roles/errors.d.ts.map +1 -0
- package/dist/modules/admin-roles/errors.js +49 -0
- package/dist/modules/admin-roles/errors.js.map +1 -0
- package/dist/modules/admin-roles/index.d.ts +30 -0
- package/dist/modules/admin-roles/index.d.ts.map +1 -0
- package/dist/modules/admin-roles/index.js +27 -0
- package/dist/modules/admin-roles/index.js.map +1 -0
- package/dist/modules/admin-roles/repository.d.ts +91 -0
- package/dist/modules/admin-roles/repository.d.ts.map +1 -0
- package/dist/modules/admin-roles/repository.js +9 -0
- package/dist/modules/admin-roles/repository.js.map +1 -0
- package/dist/modules/admin-roles/schemas.d.ts +99 -0
- package/dist/modules/admin-roles/schemas.d.ts.map +1 -0
- package/dist/modules/admin-roles/schemas.js +105 -0
- package/dist/modules/admin-roles/schemas.js.map +1 -0
- package/dist/modules/admin-roles/service.d.ts +49 -0
- package/dist/modules/admin-roles/service.d.ts.map +1 -0
- package/dist/modules/admin-roles/service.js +110 -0
- package/dist/modules/admin-roles/service.js.map +1 -0
- package/dist/modules/admin-users/abilities.d.ts +41 -0
- package/dist/modules/admin-users/abilities.d.ts.map +1 -0
- package/dist/modules/admin-users/abilities.js +70 -0
- package/dist/modules/admin-users/abilities.js.map +1 -0
- package/dist/modules/admin-users/commands.d.ts +45 -0
- package/dist/modules/admin-users/commands.d.ts.map +1 -0
- package/dist/modules/admin-users/commands.js +63 -0
- package/dist/modules/admin-users/commands.js.map +1 -0
- package/dist/modules/admin-users/dto.d.ts +20 -0
- package/dist/modules/admin-users/dto.d.ts.map +1 -0
- package/dist/modules/admin-users/dto.js +36 -0
- package/dist/modules/admin-users/dto.js.map +1 -0
- package/dist/modules/admin-users/errors.d.ts +53 -0
- package/dist/modules/admin-users/errors.d.ts.map +1 -0
- package/dist/modules/admin-users/errors.js +53 -0
- package/dist/modules/admin-users/errors.js.map +1 -0
- package/dist/modules/admin-users/index.d.ts +31 -0
- package/dist/modules/admin-users/index.d.ts.map +1 -0
- package/dist/modules/admin-users/index.js +28 -0
- package/dist/modules/admin-users/index.js.map +1 -0
- package/dist/modules/admin-users/repository.d.ts +147 -0
- package/dist/modules/admin-users/repository.d.ts.map +1 -0
- package/dist/modules/admin-users/repository.js +9 -0
- package/dist/modules/admin-users/repository.js.map +1 -0
- package/dist/modules/admin-users/schemas.d.ts +136 -0
- package/dist/modules/admin-users/schemas.d.ts.map +1 -0
- package/dist/modules/admin-users/schemas.js +137 -0
- package/dist/modules/admin-users/schemas.js.map +1 -0
- package/dist/modules/admin-users/seed-super-admin.d.ts +44 -0
- package/dist/modules/admin-users/seed-super-admin.d.ts.map +1 -0
- package/dist/modules/admin-users/seed-super-admin.js +70 -0
- package/dist/modules/admin-users/seed-super-admin.js.map +1 -0
- package/dist/modules/admin-users/service.d.ts +53 -0
- package/dist/modules/admin-users/service.d.ts.map +1 -0
- package/dist/modules/admin-users/service.js +143 -0
- package/dist/modules/admin-users/service.js.map +1 -0
- package/dist/modules/auth/index.d.ts +26 -0
- package/dist/modules/auth/index.d.ts.map +1 -0
- package/dist/modules/auth/index.js +25 -0
- package/dist/modules/auth/index.js.map +1 -0
- package/dist/modules/auth/jwt-session-provider.d.ts +47 -0
- package/dist/modules/auth/jwt-session-provider.d.ts.map +1 -0
- package/dist/modules/auth/jwt-session-provider.js +215 -0
- package/dist/modules/auth/jwt-session-provider.js.map +1 -0
- package/dist/modules/auth/password.d.ts +16 -0
- package/dist/modules/auth/password.d.ts.map +1 -0
- package/dist/modules/auth/password.js +48 -0
- package/dist/modules/auth/password.js.map +1 -0
- package/dist/modules/auth/refresh-tokens-repository.d.ts +71 -0
- package/dist/modules/auth/refresh-tokens-repository.d.ts.map +1 -0
- package/dist/modules/auth/refresh-tokens-repository.js +9 -0
- package/dist/modules/auth/refresh-tokens-repository.js.map +1 -0
- package/dist/modules/auth/resolve-actor.d.ts +25 -0
- package/dist/modules/auth/resolve-actor.d.ts.map +1 -0
- package/dist/modules/auth/resolve-actor.js +36 -0
- package/dist/modules/auth/resolve-actor.js.map +1 -0
- package/dist/store.d.ts +31 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +9 -0
- package/dist/store.js.map +1 -0
- package/package.json +101 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* `@byline/admin/auth` — session handling for the built-in admin realm.
|
|
10
|
+
*
|
|
11
|
+
* Hosts the reference `JwtSessionProvider` and the sign-in / refresh /
|
|
12
|
+
* revoke orchestration that consumes it, along with password hashing
|
|
13
|
+
* (`hashPassword` / `verifyPassword`) and the `RefreshTokensRepository`
|
|
14
|
+
* contract the provider drives.
|
|
15
|
+
*
|
|
16
|
+
* The `SessionProvider` **interface** lives in `@byline/auth` so the
|
|
17
|
+
* pluggability contract stays narrow; this module supplies the
|
|
18
|
+
* Byline-native implementation. Third-party providers (Lucia, WorkOS,
|
|
19
|
+
* Clerk, institutional SSO) should be shipped as separate packages
|
|
20
|
+
* against `@byline/auth` rather than added here.
|
|
21
|
+
*/
|
|
22
|
+
export { JwtSessionProvider } from './jwt-session-provider.js';
|
|
23
|
+
export { hashPassword, verifyPassword } from './password.js';
|
|
24
|
+
export { resolveActor } from './resolve-actor.js';
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,kBAAkB,EAAiC,MAAM,2BAA2B,CAAA;AAC7F,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
import { type AdminAuth, type RefreshSessionArgs, type SessionProvider, type SessionProviderCapabilities, type SessionTokens, type SignInResult, type SignInWithPasswordArgs } from '@byline/auth';
|
|
9
|
+
import type { AdminStore } from '../../store.js';
|
|
10
|
+
export interface JwtSessionProviderConfig {
|
|
11
|
+
/**
|
|
12
|
+
* Adapter-backed admin repositories. Construct via the DB adapter's
|
|
13
|
+
* admin-store factory (e.g. `createAdminStore(db)` from
|
|
14
|
+
* `@byline/db-postgres/admin`) and pass the result in — the provider
|
|
15
|
+
* does not touch Drizzle or any other adapter-specific API directly.
|
|
16
|
+
*/
|
|
17
|
+
store: AdminStore;
|
|
18
|
+
/**
|
|
19
|
+
* HMAC-SHA256 signing secret. Must be at least 32 bytes (256 bits) of
|
|
20
|
+
* entropy. Load from a secret manager — never hard-code.
|
|
21
|
+
*
|
|
22
|
+
* To switch to asymmetric signing (RS256/EdDSA), swap out this provider
|
|
23
|
+
* for a custom one backed by `jose` key objects.
|
|
24
|
+
*/
|
|
25
|
+
signingSecret: string | Uint8Array;
|
|
26
|
+
/** Issuer claim (`iss`) on access tokens. Defaults to `'byline'`. */
|
|
27
|
+
issuer?: string;
|
|
28
|
+
/** Access-token lifetime in seconds. Default 15 min. */
|
|
29
|
+
accessTokenTtlSeconds?: number;
|
|
30
|
+
/** Refresh-token lifetime in seconds. Default 30 days. */
|
|
31
|
+
refreshTokenTtlSeconds?: number;
|
|
32
|
+
/** Clock reference — override for deterministic tests. */
|
|
33
|
+
now?: () => Date;
|
|
34
|
+
}
|
|
35
|
+
export declare class JwtSessionProvider implements SessionProvider {
|
|
36
|
+
#private;
|
|
37
|
+
readonly capabilities: SessionProviderCapabilities;
|
|
38
|
+
constructor(config: JwtSessionProviderConfig);
|
|
39
|
+
signInWithPassword(args: SignInWithPasswordArgs): Promise<SignInResult>;
|
|
40
|
+
verifyAccessToken(token: string): Promise<{
|
|
41
|
+
actor: AdminAuth;
|
|
42
|
+
}>;
|
|
43
|
+
refreshSession(args: RefreshSessionArgs): Promise<SessionTokens>;
|
|
44
|
+
revokeSession(refreshToken: string): Promise<void>;
|
|
45
|
+
resolveActor(adminUserId: string): Promise<AdminAuth | null>;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=jwt-session-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt-session-provider.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/jwt-session-provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAEL,KAAK,SAAS,EAKd,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,2BAA2B,EAChC,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAC5B,MAAM,cAAc,CAAA;AAMrB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAYhD,MAAM,WAAW,wBAAwB;IACvC;;;;;OAKG;IACH,KAAK,EAAE,UAAU,CAAA;IACjB;;;;;;OAMG;IACH,aAAa,EAAE,MAAM,GAAG,UAAU,CAAA;IAClC,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,wDAAwD;IACxD,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,0DAA0D;IAC1D,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;CACjB;AAED,qBAAa,kBAAmB,YAAW,eAAe;;IACxD,SAAgB,YAAY,8BAAe;gBAS/B,MAAM,EAAE,wBAAwB;IAqBtC,kBAAkB,CAAC,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAAC,YAAY,CAAC;IAyCvE,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,SAAS,CAAA;KAAE,CAAC;IAwB/D,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC;IAwDhE,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlD,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;CAmDnE"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
import { createHash, randomBytes, randomUUID } from 'node:crypto';
|
|
9
|
+
import { ERR_ACCOUNT_DISABLED, ERR_INVALID_CREDENTIALS, ERR_INVALID_TOKEN, ERR_REVOKED_TOKEN, } from '@byline/auth';
|
|
10
|
+
import { jwtVerify, SignJWT } from 'jose';
|
|
11
|
+
import { v7 as uuidv7 } from 'uuid';
|
|
12
|
+
import { verifyPassword } from './password.js';
|
|
13
|
+
import { resolveActor } from './resolve-actor.js';
|
|
14
|
+
const DEFAULT_ISSUER = 'byline';
|
|
15
|
+
const DEFAULT_ACCESS_TOKEN_TTL_SECONDS = 15 * 60; // 15 minutes
|
|
16
|
+
const DEFAULT_REFRESH_TOKEN_TTL_SECONDS = 30 * 24 * 60 * 60; // 30 days
|
|
17
|
+
const CAPABILITIES = {
|
|
18
|
+
passwordChange: true,
|
|
19
|
+
magicLink: false,
|
|
20
|
+
sso: false,
|
|
21
|
+
};
|
|
22
|
+
export class JwtSessionProvider {
|
|
23
|
+
capabilities = CAPABILITIES;
|
|
24
|
+
#store;
|
|
25
|
+
#signingKey;
|
|
26
|
+
#issuer;
|
|
27
|
+
#accessTtl;
|
|
28
|
+
#refreshTtl;
|
|
29
|
+
#now;
|
|
30
|
+
constructor(config) {
|
|
31
|
+
this.#store = config.store;
|
|
32
|
+
this.#signingKey =
|
|
33
|
+
typeof config.signingSecret === 'string'
|
|
34
|
+
? new TextEncoder().encode(config.signingSecret)
|
|
35
|
+
: config.signingSecret;
|
|
36
|
+
if (this.#signingKey.byteLength < 32) {
|
|
37
|
+
throw new Error('JwtSessionProvider: signingSecret must carry at least 32 bytes of entropy (256 bits)');
|
|
38
|
+
}
|
|
39
|
+
this.#issuer = config.issuer ?? DEFAULT_ISSUER;
|
|
40
|
+
this.#accessTtl = config.accessTokenTtlSeconds ?? DEFAULT_ACCESS_TOKEN_TTL_SECONDS;
|
|
41
|
+
this.#refreshTtl = config.refreshTokenTtlSeconds ?? DEFAULT_REFRESH_TOKEN_TTL_SECONDS;
|
|
42
|
+
this.#now = config.now ?? (() => new Date());
|
|
43
|
+
}
|
|
44
|
+
// -----------------------------------------------------------------------
|
|
45
|
+
// SessionProvider
|
|
46
|
+
// -----------------------------------------------------------------------
|
|
47
|
+
async signInWithPassword(args) {
|
|
48
|
+
const users = this.#store.adminUsers;
|
|
49
|
+
const row = await users.getByEmailForSignIn(args.email);
|
|
50
|
+
// Uniform error response for unknown email vs. wrong password — don't
|
|
51
|
+
// leak which one. Still do a real verify against a dummy hash so the
|
|
52
|
+
// timing is comparable; the argon2 cost dominates regardless.
|
|
53
|
+
if (!row) {
|
|
54
|
+
await verifyPassword(args.password, DUMMY_HASH_FOR_TIMING);
|
|
55
|
+
throw ERR_INVALID_CREDENTIALS({ message: 'invalid credentials' });
|
|
56
|
+
}
|
|
57
|
+
const ok = await verifyPassword(args.password, row.password_hash);
|
|
58
|
+
if (!ok) {
|
|
59
|
+
await users.recordLoginFailure(row.id);
|
|
60
|
+
throw ERR_INVALID_CREDENTIALS({ message: 'invalid credentials' });
|
|
61
|
+
}
|
|
62
|
+
if (!row.is_enabled) {
|
|
63
|
+
throw ERR_ACCOUNT_DISABLED({ message: 'account disabled' });
|
|
64
|
+
}
|
|
65
|
+
await users.recordLoginSuccess(row.id, args.ip ?? null);
|
|
66
|
+
const actor = await resolveActor(this.#store, row.id);
|
|
67
|
+
// resolveActor also checks is_enabled, but we just recorded success
|
|
68
|
+
// above, so null here would indicate a race (the account was disabled
|
|
69
|
+
// between the check and the resolve). Treat as disabled.
|
|
70
|
+
if (!actor) {
|
|
71
|
+
throw ERR_ACCOUNT_DISABLED({ message: 'account disabled' });
|
|
72
|
+
}
|
|
73
|
+
const tokens = await this.#issueTokens({
|
|
74
|
+
adminUserId: row.id,
|
|
75
|
+
ip: args.ip ?? null,
|
|
76
|
+
userAgent: args.userAgent ?? null,
|
|
77
|
+
});
|
|
78
|
+
return { ...tokens, actor };
|
|
79
|
+
}
|
|
80
|
+
async verifyAccessToken(token) {
|
|
81
|
+
let payload;
|
|
82
|
+
try {
|
|
83
|
+
const result = await jwtVerify(token, this.#signingKey, {
|
|
84
|
+
issuer: this.#issuer,
|
|
85
|
+
});
|
|
86
|
+
payload = result.payload;
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
throw ERR_INVALID_TOKEN({ message: 'access token verification failed', cause: err });
|
|
90
|
+
}
|
|
91
|
+
if (payload.typ !== 'access') {
|
|
92
|
+
throw ERR_INVALID_TOKEN({ message: 'unexpected token type' });
|
|
93
|
+
}
|
|
94
|
+
const actor = await resolveActor(this.#store, payload.sub);
|
|
95
|
+
if (!actor) {
|
|
96
|
+
// The token was valid but the user is now disabled or deleted.
|
|
97
|
+
throw ERR_ACCOUNT_DISABLED({ message: 'account disabled or deleted' });
|
|
98
|
+
}
|
|
99
|
+
return { actor };
|
|
100
|
+
}
|
|
101
|
+
async refreshSession(args) {
|
|
102
|
+
const refreshTokens = this.#store.refreshTokens;
|
|
103
|
+
const hash = hashToken(args.refreshToken);
|
|
104
|
+
const row = await refreshTokens.findByHash(hash);
|
|
105
|
+
if (!row) {
|
|
106
|
+
throw ERR_INVALID_TOKEN({ message: 'refresh token not recognised' });
|
|
107
|
+
}
|
|
108
|
+
const now = this.#now();
|
|
109
|
+
// Already revoked?
|
|
110
|
+
if (row.revoked_at != null) {
|
|
111
|
+
if (row.rotated_to_id != null) {
|
|
112
|
+
// Rotated token replayed — the chain is compromised. Revoke every
|
|
113
|
+
// descendant so the attacker and the legitimate holder are both
|
|
114
|
+
// signed out.
|
|
115
|
+
await refreshTokens.revokeChain(row.id, now);
|
|
116
|
+
throw ERR_REVOKED_TOKEN({
|
|
117
|
+
message: 'refresh token was already rotated — chain revoked',
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
throw ERR_REVOKED_TOKEN({ message: 'refresh token has been revoked' });
|
|
121
|
+
}
|
|
122
|
+
if (row.expires_at.getTime() <= now.getTime()) {
|
|
123
|
+
throw ERR_INVALID_TOKEN({ message: 'refresh token expired' });
|
|
124
|
+
}
|
|
125
|
+
// Rotate: mint a new token, mark the old one rotated_to the new id.
|
|
126
|
+
const newId = uuidv7();
|
|
127
|
+
const newRefreshPlain = generateOpaqueToken();
|
|
128
|
+
const newRefreshHash = hashToken(newRefreshPlain);
|
|
129
|
+
const refreshExpiresAt = new Date(now.getTime() + this.#refreshTtl * 1000);
|
|
130
|
+
await refreshTokens.issue({
|
|
131
|
+
id: newId,
|
|
132
|
+
admin_user_id: row.admin_user_id,
|
|
133
|
+
token_hash: newRefreshHash,
|
|
134
|
+
expires_at: refreshExpiresAt,
|
|
135
|
+
user_agent: args.userAgent ?? null,
|
|
136
|
+
ip: args.ip ?? null,
|
|
137
|
+
});
|
|
138
|
+
await refreshTokens.markRotated(row.id, newId, now);
|
|
139
|
+
const accessToken = await this.#signAccessToken(row.admin_user_id, now);
|
|
140
|
+
const accessExpiresAt = new Date(now.getTime() + this.#accessTtl * 1000);
|
|
141
|
+
return {
|
|
142
|
+
accessToken,
|
|
143
|
+
refreshToken: newRefreshPlain,
|
|
144
|
+
accessTokenExpiresAt: accessExpiresAt,
|
|
145
|
+
refreshTokenExpiresAt: refreshExpiresAt,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
async revokeSession(refreshToken) {
|
|
149
|
+
const refreshTokens = this.#store.refreshTokens;
|
|
150
|
+
const row = await refreshTokens.findByHash(hashToken(refreshToken));
|
|
151
|
+
if (!row)
|
|
152
|
+
return; // Idempotent — unknown tokens are a no-op.
|
|
153
|
+
await refreshTokens.revoke(row.id, this.#now());
|
|
154
|
+
}
|
|
155
|
+
async resolveActor(adminUserId) {
|
|
156
|
+
return resolveActor(this.#store, adminUserId);
|
|
157
|
+
}
|
|
158
|
+
// -----------------------------------------------------------------------
|
|
159
|
+
// Internals
|
|
160
|
+
// -----------------------------------------------------------------------
|
|
161
|
+
async #issueTokens(input) {
|
|
162
|
+
const now = this.#now();
|
|
163
|
+
const refreshTokens = this.#store.refreshTokens;
|
|
164
|
+
const accessToken = await this.#signAccessToken(input.adminUserId, now);
|
|
165
|
+
const accessExpiresAt = new Date(now.getTime() + this.#accessTtl * 1000);
|
|
166
|
+
const refreshPlain = generateOpaqueToken();
|
|
167
|
+
const refreshHash = hashToken(refreshPlain);
|
|
168
|
+
const refreshExpiresAt = new Date(now.getTime() + this.#refreshTtl * 1000);
|
|
169
|
+
await refreshTokens.issue({
|
|
170
|
+
id: uuidv7(),
|
|
171
|
+
admin_user_id: input.adminUserId,
|
|
172
|
+
token_hash: refreshHash,
|
|
173
|
+
expires_at: refreshExpiresAt,
|
|
174
|
+
user_agent: input.userAgent,
|
|
175
|
+
ip: input.ip,
|
|
176
|
+
});
|
|
177
|
+
return {
|
|
178
|
+
accessToken,
|
|
179
|
+
refreshToken: refreshPlain,
|
|
180
|
+
accessTokenExpiresAt: accessExpiresAt,
|
|
181
|
+
refreshTokenExpiresAt: refreshExpiresAt,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
async #signAccessToken(adminUserId, now) {
|
|
185
|
+
const iat = Math.floor(now.getTime() / 1000);
|
|
186
|
+
const exp = iat + this.#accessTtl;
|
|
187
|
+
return new SignJWT({ typ: 'access' })
|
|
188
|
+
.setProtectedHeader({ alg: 'HS256', typ: 'JWT' })
|
|
189
|
+
.setSubject(adminUserId)
|
|
190
|
+
.setIssuer(this.#issuer)
|
|
191
|
+
.setIssuedAt(iat)
|
|
192
|
+
.setExpirationTime(exp)
|
|
193
|
+
.setJti(randomUUID())
|
|
194
|
+
.sign(this.#signingKey);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// ---------------------------------------------------------------------------
|
|
198
|
+
// Utilities
|
|
199
|
+
// ---------------------------------------------------------------------------
|
|
200
|
+
/** 32 bytes of randomness, base64url-encoded. ~43 chars on the wire. */
|
|
201
|
+
function generateOpaqueToken() {
|
|
202
|
+
return randomBytes(32).toString('base64url');
|
|
203
|
+
}
|
|
204
|
+
/** SHA-256 hex digest of the raw refresh-token string. */
|
|
205
|
+
function hashToken(token) {
|
|
206
|
+
return createHash('sha256').update(token).digest('hex');
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* A stable argon2id hash used only to equalise sign-in timing on the
|
|
210
|
+
* unknown-email code path. The plaintext here is arbitrary — we never
|
|
211
|
+
* succeed against it. This is pre-generated at module-load time so the
|
|
212
|
+
* first sign-in call doesn't pay the generation cost.
|
|
213
|
+
*/
|
|
214
|
+
const DUMMY_HASH_FOR_TIMING = '$argon2id$v=19$m=19456,t=2,p=1$c2lkZS1jaGFubmVsLW1pdGlnYXRpb24$0Hqf2vQKZqSfZZ4nJRr7K5IOjn9ngjzaQjV+yTG6iNY';
|
|
215
|
+
//# sourceMappingURL=jwt-session-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt-session-provider.js","sourceRoot":"","sources":["../../../src/modules/auth/jwt-session-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
/** Hash a plaintext password. Returns a full PHC string. */
|
|
9
|
+
export declare function hashPassword(plaintext: string): Promise<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Verify a plaintext password against a stored PHC string. Returns `false`
|
|
12
|
+
* on mismatch — never throws for a normal mismatch. Re-throws on malformed
|
|
13
|
+
* hash strings or underlying library errors so those get surfaced.
|
|
14
|
+
*/
|
|
15
|
+
export declare function verifyPassword(plaintext: string, phc: string): Promise<boolean>;
|
|
16
|
+
//# sourceMappingURL=password.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/password.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA4BH,4DAA4D;AAC5D,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKrE;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGrF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Password hashing — argon2id via @node-rs/argon2.
|
|
10
|
+
*
|
|
11
|
+
* Stores the full PHC string (`$argon2id$v=19$m=…$…$…`) in the
|
|
12
|
+
* `byline_admin_users.password` column. That makes the algorithm and
|
|
13
|
+
* parameters self-describing, so upgrading params later (or migrating off
|
|
14
|
+
* argon2id entirely) is a straightforward re-hash on next successful sign-in.
|
|
15
|
+
*
|
|
16
|
+
* Defaults follow OWASP 2023 guidance for argon2id: memory 19 MiB,
|
|
17
|
+
* iterations 2, parallelism 1. These are reasonable for typical server
|
|
18
|
+
* hardware; tune if sign-in latency becomes a concern under load.
|
|
19
|
+
*/
|
|
20
|
+
import { hash, verify } from '@node-rs/argon2';
|
|
21
|
+
/**
|
|
22
|
+
* `@node-rs/argon2` defaults to argon2id; we just tune the parameters.
|
|
23
|
+
* (The `Algorithm` enum exported by the package is a const enum and
|
|
24
|
+
* cannot be referenced under `verbatimModuleSyntax`.)
|
|
25
|
+
*/
|
|
26
|
+
const HASH_OPTIONS = {
|
|
27
|
+
memoryCost: 19456, // 19 MiB
|
|
28
|
+
timeCost: 2,
|
|
29
|
+
parallelism: 1,
|
|
30
|
+
};
|
|
31
|
+
/** Hash a plaintext password. Returns a full PHC string. */
|
|
32
|
+
export async function hashPassword(plaintext) {
|
|
33
|
+
if (plaintext.length === 0) {
|
|
34
|
+
throw new Error('hashPassword: plaintext must be non-empty');
|
|
35
|
+
}
|
|
36
|
+
return hash(plaintext, HASH_OPTIONS);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Verify a plaintext password against a stored PHC string. Returns `false`
|
|
40
|
+
* on mismatch — never throws for a normal mismatch. Re-throws on malformed
|
|
41
|
+
* hash strings or underlying library errors so those get surfaced.
|
|
42
|
+
*/
|
|
43
|
+
export async function verifyPassword(plaintext, phc) {
|
|
44
|
+
if (plaintext.length === 0 || phc.length === 0)
|
|
45
|
+
return false;
|
|
46
|
+
return verify(phc, plaintext);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=password.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password.js","sourceRoot":"","sources":["../../../src/modules/auth/password.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAE9C;;;;GAIG;AACH,MAAM,YAAY,GAAG;IACnB,UAAU,EAAE,KAAK,EAAE,SAAS;IAC5B,QAAQ,EAAE,CAAC;IACX,WAAW,EAAE,CAAC;CACf,CAAA;AAED,4DAA4D;AAC5D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAAiB;IAClD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAC9D,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAA;AACtC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,SAAiB,EAAE,GAAW;IACjE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IAC5D,OAAO,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;AAC/B,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* `RefreshTokensRepository` — the persistence contract for the
|
|
10
|
+
* `byline_admin_refresh_tokens` table.
|
|
11
|
+
*
|
|
12
|
+
* Lives under `modules/auth` rather than at the package root because this
|
|
13
|
+
* table exists to serve the built-in JWT session provider — a third-party
|
|
14
|
+
* session provider (Lucia, WorkOS, Clerk) would not use it. `token_hash`
|
|
15
|
+
* stores the SHA-256 of the plaintext refresh token; the plaintext leaves
|
|
16
|
+
* the server exactly once, when it is issued to the caller.
|
|
17
|
+
*/
|
|
18
|
+
export interface RefreshTokenRow {
|
|
19
|
+
id: string;
|
|
20
|
+
admin_user_id: string;
|
|
21
|
+
token_hash: string;
|
|
22
|
+
issued_at: Date;
|
|
23
|
+
expires_at: Date;
|
|
24
|
+
revoked_at: Date | null;
|
|
25
|
+
rotated_to_id: string | null;
|
|
26
|
+
last_used_at: Date | null;
|
|
27
|
+
user_agent: string | null;
|
|
28
|
+
ip: string | null;
|
|
29
|
+
}
|
|
30
|
+
export interface IssueRefreshTokenInput {
|
|
31
|
+
id: string;
|
|
32
|
+
admin_user_id: string;
|
|
33
|
+
token_hash: string;
|
|
34
|
+
expires_at: Date;
|
|
35
|
+
user_agent?: string | null;
|
|
36
|
+
ip?: string | null;
|
|
37
|
+
}
|
|
38
|
+
export interface RefreshTokensRepository {
|
|
39
|
+
/** Insert a new refresh-token row. `id` is supplied by the caller (UUIDv7). */
|
|
40
|
+
issue(input: IssueRefreshTokenInput): Promise<RefreshTokenRow>;
|
|
41
|
+
findByHash(tokenHash: string): Promise<RefreshTokenRow | null>;
|
|
42
|
+
findById(id: string): Promise<RefreshTokenRow | null>;
|
|
43
|
+
/** Stamp `last_used_at` for observability. */
|
|
44
|
+
touch(id: string, at?: Date): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Atomically revoke `oldId` and set its `rotated_to_id` to `newId`.
|
|
47
|
+
* Caller is responsible for inserting the new row (via `issue`) before
|
|
48
|
+
* calling this — ordering is a contract.
|
|
49
|
+
*/
|
|
50
|
+
markRotated(oldId: string, newId: string, at?: Date): Promise<void>;
|
|
51
|
+
/** Revoke a single token. Idempotent. */
|
|
52
|
+
revoke(id: string, at?: Date): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Walk the rotation chain starting at `startId` and revoke every token
|
|
55
|
+
* in it. Called when a rotated token is replayed — indicates the chain
|
|
56
|
+
* has been compromised and every descendant is suspect. Returns the
|
|
57
|
+
* number of rows touched.
|
|
58
|
+
*/
|
|
59
|
+
revokeChain(startId: string, at?: Date): Promise<number>;
|
|
60
|
+
/** Revoke every non-revoked token for a user. Used on password change / sign-out everywhere. */
|
|
61
|
+
revokeAllForUser(adminUserId: string, at?: Date): Promise<number>;
|
|
62
|
+
/** Remove rows whose `expires_at` is in the past. Housekeeping. */
|
|
63
|
+
purgeExpired(now?: Date): Promise<number>;
|
|
64
|
+
/** All non-revoked tokens for a user. Primarily for tests. */
|
|
65
|
+
listActiveForUser(adminUserId: string): Promise<RefreshTokenRow[]>;
|
|
66
|
+
/** All tokens (including revoked) for a user. Primarily for tests and debugging. */
|
|
67
|
+
listAllForUser(adminUserId: string): Promise<RefreshTokenRow[]>;
|
|
68
|
+
/** All tokens descended from `startId` via the rotation chain. Utility for tests. */
|
|
69
|
+
listRotationChain(startId: string): Promise<RefreshTokenRow[]>;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=refresh-tokens-repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh-tokens-repository.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/refresh-tokens-repository.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;GASG;AAEH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,IAAI,CAAA;IACf,UAAU,EAAE,IAAI,CAAA;IAChB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAA;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,YAAY,EAAE,IAAI,GAAG,IAAI,CAAA;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAA;IACV,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,IAAI,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,+EAA+E;IAC/E,KAAK,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IAC9D,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAA;IAC9D,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAA;IACrD,8CAA8C;IAC9C,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3C;;;;OAIG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACnE,yCAAyC;IACzC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C;;;;;OAKG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACxD,gGAAgG;IAChG,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACjE,mEAAmE;IACnE,YAAY,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACzC,8DAA8D;IAC9D,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAA;IAClE,oFAAoF;IACpF,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAA;IAC/D,qFAAqF;IACrF,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAA;CAC/D"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=refresh-tokens-repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh-tokens-repository.js","sourceRoot":"","sources":["../../../src/modules/auth/refresh-tokens-repository.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
import { AdminAuth } from '@byline/auth';
|
|
9
|
+
import type { AdminStore } from '../../store.js';
|
|
10
|
+
/**
|
|
11
|
+
* Build an `AdminAuth` from a user id by reading the admin-users row and
|
|
12
|
+
* collecting the distinct abilities granted through every role the user
|
|
13
|
+
* holds.
|
|
14
|
+
*
|
|
15
|
+
* Returns `null` when the user does not exist or is not enabled — callers
|
|
16
|
+
* interpret a null result as "no actor, sign-in refused". The enablement
|
|
17
|
+
* check lives here (rather than in the session provider) so that any code
|
|
18
|
+
* path resolving an actor from a stored user id — sign-in, token refresh,
|
|
19
|
+
* seeded super-admin context — applies the same gate.
|
|
20
|
+
*
|
|
21
|
+
* Consumes the admin-users and admin-permissions repositories through the
|
|
22
|
+
* `AdminStore` bundle; adapter-agnostic.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveActor(store: AdminStore, adminUserId: string): Promise<AdminAuth | null>;
|
|
25
|
+
//# sourceMappingURL=resolve-actor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-actor.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/resolve-actor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAExC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAEhD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAY3B"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
import { AdminAuth } from '@byline/auth';
|
|
9
|
+
/**
|
|
10
|
+
* Build an `AdminAuth` from a user id by reading the admin-users row and
|
|
11
|
+
* collecting the distinct abilities granted through every role the user
|
|
12
|
+
* holds.
|
|
13
|
+
*
|
|
14
|
+
* Returns `null` when the user does not exist or is not enabled — callers
|
|
15
|
+
* interpret a null result as "no actor, sign-in refused". The enablement
|
|
16
|
+
* check lives here (rather than in the session provider) so that any code
|
|
17
|
+
* path resolving an actor from a stored user id — sign-in, token refresh,
|
|
18
|
+
* seeded super-admin context — applies the same gate.
|
|
19
|
+
*
|
|
20
|
+
* Consumes the admin-users and admin-permissions repositories through the
|
|
21
|
+
* `AdminStore` bundle; adapter-agnostic.
|
|
22
|
+
*/
|
|
23
|
+
export async function resolveActor(store, adminUserId) {
|
|
24
|
+
const user = await store.adminUsers.getById(adminUserId);
|
|
25
|
+
if (!user)
|
|
26
|
+
return null;
|
|
27
|
+
if (!user.is_enabled)
|
|
28
|
+
return null;
|
|
29
|
+
const abilities = await store.adminPermissions.listAbilitiesForUser(adminUserId);
|
|
30
|
+
return new AdminAuth({
|
|
31
|
+
id: user.id,
|
|
32
|
+
abilities,
|
|
33
|
+
isSuperAdmin: user.is_super_admin,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=resolve-actor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-actor.js","sourceRoot":"","sources":["../../../src/modules/auth/resolve-actor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAIxC;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAiB,EACjB,WAAmB;IAEnB,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IACxD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAA;IACtB,IAAI,CAAC,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAA;IAEjC,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAA;IAEhF,OAAO,IAAI,SAAS,CAAC;QACnB,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,SAAS;QACT,YAAY,EAAE,IAAI,CAAC,cAAc;KAClC,CAAC,CAAA;AACJ,CAAC"}
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
import type { AdminPermissionsRepository } from './modules/admin-permissions/repository.js';
|
|
9
|
+
import type { AdminRolesRepository } from './modules/admin-roles/repository.js';
|
|
10
|
+
import type { AdminUsersRepository } from './modules/admin-users/repository.js';
|
|
11
|
+
import type { RefreshTokensRepository } from './modules/auth/refresh-tokens-repository.js';
|
|
12
|
+
/**
|
|
13
|
+
* The bundle of repositories that `@byline/admin` needs from the DB
|
|
14
|
+
* adapter. A DB adapter package (`@byline/db-postgres`, a future
|
|
15
|
+
* `@byline/db-mysql`) is expected to expose a factory — conventionally
|
|
16
|
+
* `createAdminStore(db)` — that returns an `AdminStore` wired against
|
|
17
|
+
* its concrete schema. The bundle is passed to the built-in
|
|
18
|
+
* `JwtSessionProvider`, to `seedSuperAdmin`, and (later) to admin-user
|
|
19
|
+
* and admin-role commands.
|
|
20
|
+
*
|
|
21
|
+
* Keeping the four repositories together as a single argument avoids
|
|
22
|
+
* exploding constructor signatures and makes "needs admin DB access" a
|
|
23
|
+
* single, recognisable type.
|
|
24
|
+
*/
|
|
25
|
+
export interface AdminStore {
|
|
26
|
+
adminUsers: AdminUsersRepository;
|
|
27
|
+
adminRoles: AdminRolesRepository;
|
|
28
|
+
adminPermissions: AdminPermissionsRepository;
|
|
29
|
+
refreshTokens: RefreshTokensRepository;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAA;AAC3F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAA;AAC/E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAA;AAC/E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,6CAA6C,CAAA;AAE1F;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,oBAAoB,CAAA;IAChC,UAAU,EAAE,oBAAoB,CAAA;IAChC,gBAAgB,EAAE,0BAA0B,CAAA;IAC5C,aAAa,EAAE,uBAAuB,CAAA;CACvC"}
|
package/dist/store.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|