@nocobase/app-plugin-api-keys 0.0.0-stage → 1.0.0-beta.13
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 +418 -0
- package/README.md +165 -2
- package/dist/client/api-keys-client.d.ts +19 -0
- package/dist/client/api-keys-client.d.ts.map +1 -0
- package/dist/client/api-keys-client.js +7 -0
- package/dist/client/api-keys-client.js.map +1 -0
- package/dist/client/components/page-container.d.ts +4 -0
- package/dist/client/components/page-container.d.ts.map +1 -0
- package/dist/client/components/page-container.js +6 -0
- package/dist/client/components/page-container.js.map +1 -0
- package/dist/client/components/page-header.d.ts +8 -0
- package/dist/client/components/page-header.d.ts.map +1 -0
- package/dist/client/components/page-header.js +5 -0
- package/dist/client/components/page-header.js.map +1 -0
- package/dist/client/components/ui/alert-dialog.d.ts +19 -0
- package/dist/client/components/ui/alert-dialog.d.ts.map +1 -0
- package/dist/client/components/ui/alert-dialog.js +42 -0
- package/dist/client/components/ui/alert-dialog.js.map +1 -0
- package/dist/client/components/ui/badge.d.ts +6 -0
- package/dist/client/components/ui/badge.d.ts.map +1 -0
- package/dist/client/components/ui/badge.js +8 -0
- package/dist/client/components/ui/badge.js.map +1 -0
- package/dist/client/components/ui/button.d.ts +8 -0
- package/dist/client/components/ui/button.d.ts.map +1 -0
- package/dist/client/components/ui/button.js +27 -0
- package/dist/client/components/ui/button.js.map +1 -0
- package/dist/client/components/ui/dialog.d.ts +9 -0
- package/dist/client/components/ui/dialog.d.ts.map +1 -0
- package/dist/client/components/ui/dialog.js +29 -0
- package/dist/client/components/ui/dialog.js.map +1 -0
- package/dist/client/components/ui/input.d.ts +4 -0
- package/dist/client/components/ui/input.d.ts.map +1 -0
- package/dist/client/components/ui/input.js +8 -0
- package/dist/client/components/ui/input.js.map +1 -0
- package/dist/client/components/ui/label.d.ts +3 -0
- package/dist/client/components/ui/label.d.ts.map +1 -0
- package/dist/client/components/ui/label.js +6 -0
- package/dist/client/components/ui/label.js.map +1 -0
- package/dist/client/components/ui/select.d.ts +8 -0
- package/dist/client/components/ui/select.d.ts.map +1 -0
- package/dist/client/components/ui/select.js +19 -0
- package/dist/client/components/ui/select.js.map +1 -0
- package/dist/client/components/ui/spinner.d.ts +4 -0
- package/dist/client/components/ui/spinner.d.ts.map +1 -0
- package/dist/client/components/ui/spinner.js +11 -0
- package/dist/client/components/ui/spinner.js.map +1 -0
- package/dist/client/components/ui/table.d.ts +8 -0
- package/dist/client/components/ui/table.d.ts.map +1 -0
- package/dist/client/components/ui/table.js +21 -0
- package/dist/client/components/ui/table.js.map +1 -0
- package/dist/client/expiry.d.ts +23 -0
- package/dist/client/expiry.d.ts.map +1 -0
- package/dist/client/expiry.js +40 -0
- package/dist/client/expiry.js.map +1 -0
- package/dist/client/index.d.ts +6 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +7 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/lib/utils.d.ts +2 -0
- package/dist/client/lib/utils.d.ts.map +1 -0
- package/dist/client/lib/utils.js +2 -0
- package/dist/client/lib/utils.js.map +1 -0
- package/dist/client/locales/en-US.d.ts +71 -0
- package/dist/client/locales/en-US.d.ts.map +1 -0
- package/dist/client/locales/en-US.js +62 -0
- package/dist/client/locales/en-US.js.map +1 -0
- package/dist/client/locales/index.d.ts +4 -0
- package/dist/client/locales/index.d.ts.map +1 -0
- package/dist/client/locales/index.js +7 -0
- package/dist/client/locales/index.js.map +1 -0
- package/dist/client/locales/zh-CN.d.ts +4 -0
- package/dist/client/locales/zh-CN.d.ts.map +1 -0
- package/dist/client/locales/zh-CN.js +62 -0
- package/dist/client/locales/zh-CN.js.map +1 -0
- package/dist/client/pages/api-keys-page.d.ts +3 -0
- package/dist/client/pages/api-keys-page.d.ts.map +1 -0
- package/dist/client/pages/api-keys-page.js +161 -0
- package/dist/client/pages/api-keys-page.js.map +1 -0
- package/dist/client/plugin.d.ts +9 -0
- package/dist/client/plugin.d.ts.map +1 -0
- package/dist/client/plugin.js +10 -0
- package/dist/client/plugin.js.map +1 -0
- package/dist/client/routes.d.ts +22 -0
- package/dist/client/routes.d.ts.map +1 -0
- package/dist/client/routes.js +42 -0
- package/dist/client/routes.js.map +1 -0
- package/dist/database/migrations/.manifest.json +9 -0
- package/dist/database/migrations/202609150001_create_api_key_table.js +58 -0
- package/dist/database/migrations/202609150001_create_api_key_table.js.map +1 -0
- package/dist/server/api-docs.d.ts +24 -0
- package/dist/server/api-docs.d.ts.map +1 -0
- package/dist/server/api-docs.js +73 -0
- package/dist/server/api-docs.js.map +1 -0
- package/dist/server/api-keys.d.ts +52 -0
- package/dist/server/api-keys.d.ts.map +1 -0
- package/dist/server/api-keys.js +199 -0
- package/dist/server/api-keys.js.map +1 -0
- package/dist/server/index.d.ts +23 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +22 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/key-sessions.d.ts +35 -0
- package/dist/server/key-sessions.d.ts.map +1 -0
- package/dist/server/key-sessions.js +50 -0
- package/dist/server/key-sessions.js.map +1 -0
- package/dist/server/plugin.d.ts +4 -0
- package/dist/server/plugin.d.ts.map +1 -0
- package/dist/server/plugin.js +15 -0
- package/dist/server/plugin.js.map +1 -0
- package/dist/server/providers/index.d.ts +19 -0
- package/dist/server/providers/index.d.ts.map +1 -0
- package/dist/server/providers/index.js +72 -0
- package/dist/server/providers/index.js.map +1 -0
- package/dist/server/routes/errors.d.ts +8 -0
- package/dist/server/routes/errors.d.ts.map +1 -0
- package/dist/server/routes/errors.js +48 -0
- package/dist/server/routes/errors.js.map +1 -0
- package/dist/server/routes/index.d.ts +10 -0
- package/dist/server/routes/index.d.ts.map +1 -0
- package/dist/server/routes/index.js +177 -0
- package/dist/server/routes/index.js.map +1 -0
- package/dist/server/routes/schemas.d.ts +25 -0
- package/dist/server/routes/schemas.d.ts.map +1 -0
- package/dist/server/routes/schemas.js +127 -0
- package/dist/server/routes/schemas.js.map +1 -0
- package/dist/server/scoped-keys.d.ts +116 -0
- package/dist/server/scoped-keys.d.ts.map +1 -0
- package/dist/server/scoped-keys.js +451 -0
- package/dist/server/scoped-keys.js.map +1 -0
- package/dist/server/scopes.d.ts +70 -0
- package/dist/server/scopes.d.ts.map +1 -0
- package/dist/server/scopes.js +165 -0
- package/dist/server/scopes.js.map +1 -0
- package/dist/server/service.d.ts +28 -0
- package/dist/server/service.d.ts.map +1 -0
- package/dist/server/service.js +69 -0
- package/dist/server/service.js.map +1 -0
- package/dist/server/tokens.d.ts +6 -0
- package/dist/server/tokens.d.ts.map +1 -0
- package/dist/server/tokens.js +5 -0
- package/dist/server/tokens.js.map +1 -0
- package/dist/shared/scopes.d.ts +160 -0
- package/dist/shared/scopes.d.ts.map +1 -0
- package/dist/shared/scopes.js +83 -0
- package/dist/shared/scopes.js.map +1 -0
- package/package.json +91 -3
- package/skills/nocobase-app-plugin-api-keys/SKILL.md +166 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keys with scopes: creating, listing, rotating and revoking a user's keys, and recognizing the key behind a request.
|
|
3
|
+
* The caller authorizes who may manage whose keys; this service only ever acts on the user it is told.
|
|
4
|
+
*/
|
|
5
|
+
import { type Auth, type AuthSession } from '@nocobase/app-plugin-authentication/server';
|
|
6
|
+
import type { Authorization, AuthorizationIdentity, KeyScope } from '@nocobase/authorization/core';
|
|
7
|
+
import type { DatabaseConnection } from '@nocobase/db';
|
|
8
|
+
import { type ApiKeyView, type CreatedApiKey, type KeyScopeInput, type KeyScopeObject, type KeyScopeOptions } from '../shared/scopes.js';
|
|
9
|
+
import { type ApiKeyScopes } from './scopes.js';
|
|
10
|
+
/** The expiry the editor proposes for a scoped key. */
|
|
11
|
+
export declare const DEFAULT_SCOPED_KEY_DAYS = 90;
|
|
12
|
+
/** `apiKeys` in the application's configuration. */
|
|
13
|
+
export interface ApiKeysConfig {
|
|
14
|
+
/** The longest a scoped key may live, in days. Unset allows "never expires". */
|
|
15
|
+
readonly maxScopedKeyDays?: number | null;
|
|
16
|
+
}
|
|
17
|
+
/** A refused key operation: a status and a stable code. */
|
|
18
|
+
export declare class ApiKeyRequestError extends Error {
|
|
19
|
+
readonly status: 400 | 403 | 404;
|
|
20
|
+
readonly code: string;
|
|
21
|
+
constructor(status: 400 | 403 | 404, code: string, message: string);
|
|
22
|
+
}
|
|
23
|
+
export interface ScopedApiKeysOptions {
|
|
24
|
+
readonly auth: Pick<Auth, 'pluginApi'>;
|
|
25
|
+
readonly connection: () => DatabaseConnection;
|
|
26
|
+
readonly scopes: ApiKeyScopes;
|
|
27
|
+
/** The application's authorization, to say what a user holds and to build their identity; optional. */
|
|
28
|
+
readonly authorization?: () => Authorization | undefined;
|
|
29
|
+
readonly config?: () => ApiKeysConfig | undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Whether a user may create (and rotate) keys of their own, as an application decides it. Without one, everyone may.
|
|
33
|
+
* Listing and revoking one's keys stay open, so a person who loses the permission can still clean up.
|
|
34
|
+
*/
|
|
35
|
+
export type OwnKeyPolicy = (userId: string) => Promise<boolean>;
|
|
36
|
+
/** A key's fields as `create` would issue it, checked but not yet issued (`ScopedApiKeys.check`). */
|
|
37
|
+
export interface CheckedApiKey {
|
|
38
|
+
readonly name: string;
|
|
39
|
+
readonly description: string | null;
|
|
40
|
+
readonly scope: KeyScopeInput | null;
|
|
41
|
+
readonly expiresInDays: number | null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Lets the hook on Better Auth's own `/api-key/create` ask `keys` whether a person may create a key of their own, as
|
|
45
|
+
* `/api/apiKeys` does. The plugin's provider calls it at boot; returns what disconnects it.
|
|
46
|
+
*/
|
|
47
|
+
export declare function connectOwnKeyPolicy(auth: Pick<Auth, 'administrationContext'>, keys: Pick<ScopedApiKeys, 'mayCreateOwn'>): Promise<() => void>;
|
|
48
|
+
export declare class ScopedApiKeys {
|
|
49
|
+
private readonly options;
|
|
50
|
+
private readonly resolved;
|
|
51
|
+
private ownKeyPolicy;
|
|
52
|
+
constructor(options: ScopedApiKeysOptions);
|
|
53
|
+
/**
|
|
54
|
+
* Sets who may create keys of their own (`/api/apiKeys` and Better Auth's `/api-key/create`). Returns what removes
|
|
55
|
+
* it again.
|
|
56
|
+
*/
|
|
57
|
+
setOwnKeyPolicy(policy: OwnKeyPolicy): () => void;
|
|
58
|
+
/** Whether `userId` may create keys of their own; true unless the application set a policy that says otherwise. */
|
|
59
|
+
mayCreateOwn(userId: string): Promise<boolean>;
|
|
60
|
+
/** Refuses with 403 `API_KEY_CREATION_FORBIDDEN` unless `userId` may create keys of their own. */
|
|
61
|
+
requireOwnCreation(userId: string): Promise<void>;
|
|
62
|
+
private get maxScopedKeyDays();
|
|
63
|
+
/** The identity a request of `userId` would carry, as the authorization plugin's middleware builds it. */
|
|
64
|
+
identityOf(userId: string): Promise<AuthorizationIdentity>;
|
|
65
|
+
/** What the editor offers for keys of `userId`, with what that user holds today. */
|
|
66
|
+
scopeOptions(userId: string): Promise<KeyScopeOptions>;
|
|
67
|
+
/** The records a group may be limited to, as `identity` may see them. */
|
|
68
|
+
scopeObjects(groupId: string, identity: AuthorizationIdentity, query?: {
|
|
69
|
+
readonly search?: string;
|
|
70
|
+
readonly ids?: readonly string[];
|
|
71
|
+
}): Promise<readonly KeyScopeObject[]>;
|
|
72
|
+
/** `userId`'s keys of the default configuration, newest first. */
|
|
73
|
+
list(userId: string): Promise<ApiKeyView[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Creates a key for `userId`. `identity` is whoever chooses the records of a group limited to some: each must be
|
|
76
|
+
* one they may see.
|
|
77
|
+
*/
|
|
78
|
+
create(userId: string, input: unknown, identity: AuthorizationIdentity): Promise<CreatedApiKey>;
|
|
79
|
+
/**
|
|
80
|
+
* Checks what `create` would issue — name, description, scope, the records it picks (`identity` must see each) and
|
|
81
|
+
* expiry — without issuing anything, so a caller can refuse before creating whatever the key belongs to.
|
|
82
|
+
*/
|
|
83
|
+
check(input: unknown, identity: AuthorizationIdentity): Promise<CheckedApiKey>;
|
|
84
|
+
/** Issues a key `check` accepted. */
|
|
85
|
+
issueChecked(userId: string, input: CheckedApiKey): Promise<CreatedApiKey>;
|
|
86
|
+
/** One of `userId`'s keys. */
|
|
87
|
+
get(userId: string, keyId: string): Promise<ApiKeyView>;
|
|
88
|
+
/**
|
|
89
|
+
* Gives a key a new secret in place: the same key — id, name, description, scope and owner — with a new value, and
|
|
90
|
+
* an expiry renewed for the lifetime it had. The old value stops at once.
|
|
91
|
+
*/
|
|
92
|
+
rotate(userId: string, keyId: string): Promise<CreatedApiKey>;
|
|
93
|
+
/**
|
|
94
|
+
* Replaces a key's scope. `identity` is whoever chooses it: each record a group is limited to must be one they may
|
|
95
|
+
* see. The caller decides who may change a key and whether the new scope is one they may give. A key without a scope
|
|
96
|
+
* cannot be given one this way, nor the reverse.
|
|
97
|
+
*/
|
|
98
|
+
setScope(userId: string, keyId: string, input: unknown, identity: AuthorizationIdentity): Promise<ApiKeyView>;
|
|
99
|
+
/** Renames a key or changes its description; a field left out stays. */
|
|
100
|
+
update(userId: string, keyId: string, input: unknown): Promise<ApiKeyView>;
|
|
101
|
+
revoke(userId: string, keyId: string): Promise<void>;
|
|
102
|
+
/** Every key of `userId`, as when the account is deleted. */
|
|
103
|
+
revokeAll(userId: string): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* The scope of the key a request authenticated with: compiled from its stored scope, unbounded for a service
|
|
106
|
+
* account's unscoped key, and null for a session or a person's unscoped key. Read once per request.
|
|
107
|
+
*/
|
|
108
|
+
resolve(session: NonNullable<AuthSession>, request: Request): Promise<KeyScope | null>;
|
|
109
|
+
private lookup;
|
|
110
|
+
private issue;
|
|
111
|
+
private remove;
|
|
112
|
+
private requireRow;
|
|
113
|
+
private checkObjects;
|
|
114
|
+
private expiryOf;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=scoped-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoped-keys.d.ts","sourceRoot":"","sources":["../../server/scoped-keys.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keys with scopes: creating, listing, rotating and revoking a user's keys, and recognizing the key behind a request.
|
|
3
|
+
* The caller authorizes who may manage whose keys; this service only ever acts on the user it is told.
|
|
4
|
+
*/
|
|
5
|
+
import { isServiceAccount, } from '@nocobase/app-plugin-authentication/server';
|
|
6
|
+
import { decodeKeyScope, encodeKeyScope, KEY_SCOPE_LEVELS, pickedObjects, } from '../shared/scopes.js';
|
|
7
|
+
import { ownKeyPolicySlotOf } from './api-keys.js';
|
|
8
|
+
import { API_KEY_HEADER, isApiKeySession } from './key-sessions.js';
|
|
9
|
+
import { ApiKeyScopeError } from './scopes.js';
|
|
10
|
+
/** The expiry the editor proposes for a scoped key. */
|
|
11
|
+
export const DEFAULT_SCOPED_KEY_DAYS = 90;
|
|
12
|
+
/** A refused key operation: a status and a stable code. */
|
|
13
|
+
export class ApiKeyRequestError extends Error {
|
|
14
|
+
status;
|
|
15
|
+
code;
|
|
16
|
+
constructor(status, code, message) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.status = status;
|
|
19
|
+
this.code = code;
|
|
20
|
+
this.name = 'ApiKeyRequestError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const DAY_SECONDS = 24 * 60 * 60;
|
|
24
|
+
const MAX_NAME = 100;
|
|
25
|
+
const MAX_DESCRIPTION = 500;
|
|
26
|
+
/**
|
|
27
|
+
* Lets the hook on Better Auth's own `/api-key/create` ask `keys` whether a person may create a key of their own, as
|
|
28
|
+
* `/api/apiKeys` does. The plugin's provider calls it at boot; returns what disconnects it.
|
|
29
|
+
*/
|
|
30
|
+
export async function connectOwnKeyPolicy(auth, keys) {
|
|
31
|
+
const context = await auth.administrationContext();
|
|
32
|
+
const slots = (context.options.plugins ?? [])
|
|
33
|
+
.map((plugin) => ownKeyPolicySlotOf(plugin))
|
|
34
|
+
.filter((slot) => slot !== undefined);
|
|
35
|
+
const check = (userId) => keys.mayCreateOwn(userId);
|
|
36
|
+
for (const slot of slots)
|
|
37
|
+
slot.current = check;
|
|
38
|
+
return () => {
|
|
39
|
+
for (const slot of slots)
|
|
40
|
+
if (slot.current === check)
|
|
41
|
+
slot.current = null;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export class ScopedApiKeys {
|
|
45
|
+
options;
|
|
46
|
+
resolved = new WeakMap();
|
|
47
|
+
ownKeyPolicy = null;
|
|
48
|
+
constructor(options) {
|
|
49
|
+
this.options = options;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Sets who may create keys of their own (`/api/apiKeys` and Better Auth's `/api-key/create`). Returns what removes
|
|
53
|
+
* it again.
|
|
54
|
+
*/
|
|
55
|
+
setOwnKeyPolicy(policy) {
|
|
56
|
+
this.ownKeyPolicy = policy;
|
|
57
|
+
return () => {
|
|
58
|
+
if (this.ownKeyPolicy === policy)
|
|
59
|
+
this.ownKeyPolicy = null;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/** Whether `userId` may create keys of their own; true unless the application set a policy that says otherwise. */
|
|
63
|
+
async mayCreateOwn(userId) {
|
|
64
|
+
return this.ownKeyPolicy ? this.ownKeyPolicy(userId) : true;
|
|
65
|
+
}
|
|
66
|
+
/** Refuses with 403 `API_KEY_CREATION_FORBIDDEN` unless `userId` may create keys of their own. */
|
|
67
|
+
async requireOwnCreation(userId) {
|
|
68
|
+
if (!(await this.mayCreateOwn(userId)))
|
|
69
|
+
throw new ApiKeyRequestError(403, 'API_KEY_CREATION_FORBIDDEN', 'You may not create API keys of your own.');
|
|
70
|
+
}
|
|
71
|
+
get maxScopedKeyDays() {
|
|
72
|
+
const value = this.options.config?.()?.maxScopedKeyDays;
|
|
73
|
+
return typeof value === 'number' && Number.isInteger(value) && value > 0
|
|
74
|
+
? value
|
|
75
|
+
: null;
|
|
76
|
+
}
|
|
77
|
+
/** The identity a request of `userId` would carry, as the authorization plugin's middleware builds it. */
|
|
78
|
+
async identityOf(userId) {
|
|
79
|
+
const principal = { type: 'user', id: userId };
|
|
80
|
+
const authz = this.options.authorization?.();
|
|
81
|
+
return {
|
|
82
|
+
principal,
|
|
83
|
+
subjects: [
|
|
84
|
+
{ type: 'authenticated', id: '*' },
|
|
85
|
+
...(authz ? await authz.subjects.resolveFor(principal) : []),
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/** What the editor offers for keys of `userId`, with what that user holds today. */
|
|
90
|
+
async scopeOptions(userId) {
|
|
91
|
+
const authz = this.options.authorization?.();
|
|
92
|
+
const context = authz ? authz.for(await this.identityOf(userId)) : null;
|
|
93
|
+
const groups = await Promise.all(this.options.scopes.groups.list().map(async (group) => {
|
|
94
|
+
const levels = KEY_SCOPE_LEVELS.filter((level) => group.levels[level] !== undefined);
|
|
95
|
+
const held = {};
|
|
96
|
+
for (const level of levels) {
|
|
97
|
+
const access = this.options.scopes.accessOf(group, level);
|
|
98
|
+
// A ref is held when any of its actions is (a business action at any of its levels).
|
|
99
|
+
held[level] = context
|
|
100
|
+
? (await Promise.all(access.map(async ({ resource, actions }) => (await Promise.all(actions.map((action) => context.can({ resource, action })))).some(Boolean)))).every(Boolean)
|
|
101
|
+
: true;
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
id: group.id,
|
|
105
|
+
category: group.category,
|
|
106
|
+
title: group.title,
|
|
107
|
+
description: group.description ?? null,
|
|
108
|
+
levels,
|
|
109
|
+
access: group.levels,
|
|
110
|
+
held,
|
|
111
|
+
objects: group.objects
|
|
112
|
+
? { business: group.objects.business, title: group.objects.title }
|
|
113
|
+
: null,
|
|
114
|
+
};
|
|
115
|
+
}));
|
|
116
|
+
return {
|
|
117
|
+
groups,
|
|
118
|
+
presets: this.options.scopes.presets.list().map((preset) => ({
|
|
119
|
+
id: preset.id,
|
|
120
|
+
title: preset.title,
|
|
121
|
+
description: preset.description ?? null,
|
|
122
|
+
groups: preset.groups,
|
|
123
|
+
expiresInDays: preset.expiresInDays ?? null,
|
|
124
|
+
})),
|
|
125
|
+
maxScopedKeyDays: this.maxScopedKeyDays,
|
|
126
|
+
defaultExpiresInDays: Math.min(DEFAULT_SCOPED_KEY_DAYS, this.maxScopedKeyDays ?? DEFAULT_SCOPED_KEY_DAYS),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/** The records a group may be limited to, as `identity` may see them. */
|
|
130
|
+
async scopeObjects(groupId, identity, query = {}) {
|
|
131
|
+
const source = this.options.scopes.groups.objects(groupId);
|
|
132
|
+
if (!source)
|
|
133
|
+
throw new ApiKeyRequestError(404, 'UNKNOWN_SCOPE_GROUP', `${groupId} has no records to choose from.`);
|
|
134
|
+
return source.list({ identity, ...query });
|
|
135
|
+
}
|
|
136
|
+
/** `userId`'s keys of the default configuration, newest first. */
|
|
137
|
+
async list(userId) {
|
|
138
|
+
const rows = await this.options
|
|
139
|
+
.connection()
|
|
140
|
+
.query.selectFrom('apikey')
|
|
141
|
+
.selectAll()
|
|
142
|
+
.where('referenceId', '=', userId)
|
|
143
|
+
.where('configId', '=', 'default')
|
|
144
|
+
.orderBy('createdAt', 'desc')
|
|
145
|
+
.orderBy('id', 'asc')
|
|
146
|
+
.execute();
|
|
147
|
+
return rows.map((row) => viewOf(row));
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Creates a key for `userId`. `identity` is whoever chooses the records of a group limited to some: each must be
|
|
151
|
+
* one they may see.
|
|
152
|
+
*/
|
|
153
|
+
async create(userId, input, identity) {
|
|
154
|
+
return this.issue(userId, await this.check(input, identity));
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Checks what `create` would issue — name, description, scope, the records it picks (`identity` must see each) and
|
|
158
|
+
* expiry — without issuing anything, so a caller can refuse before creating whatever the key belongs to.
|
|
159
|
+
*/
|
|
160
|
+
async check(input, identity) {
|
|
161
|
+
const body = isRecord(input) ? input : {};
|
|
162
|
+
const name = text(body.name, 'name', MAX_NAME, true);
|
|
163
|
+
const description = text(body.description, 'description', MAX_DESCRIPTION, false);
|
|
164
|
+
const scope = body.scope === null || body.scope === undefined
|
|
165
|
+
? null
|
|
166
|
+
: this.options.scopes.validate(body.scope);
|
|
167
|
+
if (scope)
|
|
168
|
+
await this.checkObjects(scope, identity);
|
|
169
|
+
const expiresInDays = this.expiryOf(body.expiresInDays, scope !== null);
|
|
170
|
+
return { name, description, scope, expiresInDays };
|
|
171
|
+
}
|
|
172
|
+
/** Issues a key `check` accepted. */
|
|
173
|
+
issueChecked(userId, input) {
|
|
174
|
+
return this.issue(userId, input);
|
|
175
|
+
}
|
|
176
|
+
/** One of `userId`'s keys. */
|
|
177
|
+
async get(userId, keyId) {
|
|
178
|
+
return viewOf(await this.requireRow(userId, keyId));
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Gives a key a new secret in place: the same key — id, name, description, scope and owner — with a new value, and
|
|
182
|
+
* an expiry renewed for the lifetime it had. The old value stops at once.
|
|
183
|
+
*/
|
|
184
|
+
async rotate(userId, keyId) {
|
|
185
|
+
const row = await this.requireRow(userId, keyId);
|
|
186
|
+
const created = parseDate(row.createdAt);
|
|
187
|
+
const expires = row.expiresAt == null ? null : parseDate(row.expiresAt);
|
|
188
|
+
const lifetime = created && expires
|
|
189
|
+
? Math.max(1, Math.round((expires.getTime() - created.getTime()) / 86_400_000))
|
|
190
|
+
: null;
|
|
191
|
+
// Better Auth generates and hashes the new value, as for any key (its prefix, length and hashing options apply);
|
|
192
|
+
// the value moves onto the existing row and the row Better Auth made for it goes.
|
|
193
|
+
const endpoints = this.options.auth.pluginApi('api-key');
|
|
194
|
+
const fresh = await endpoints.createApiKey({
|
|
195
|
+
body: {
|
|
196
|
+
userId,
|
|
197
|
+
name: row.name ?? 'API key',
|
|
198
|
+
...(lifetime === null ? {} : { expiresIn: lifetime * DAY_SECONDS }),
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
const value = await this.options
|
|
202
|
+
.connection()
|
|
203
|
+
.query.selectFrom('apikey')
|
|
204
|
+
.select(['key', 'start', 'prefix', 'expiresAt', 'createdAt', 'updatedAt'])
|
|
205
|
+
.where('id', '=', fresh.id)
|
|
206
|
+
.executeTakeFirst();
|
|
207
|
+
try {
|
|
208
|
+
if (!value)
|
|
209
|
+
throw new Error('The rotated key was not stored.');
|
|
210
|
+
// Stored as Better Auth stored them for the new value, so its own reads see the same encoding. `createdAt` is
|
|
211
|
+
// when the current value was issued, which the renewed lifetime counts from.
|
|
212
|
+
await this.options
|
|
213
|
+
.connection()
|
|
214
|
+
.query.updateTable('apikey')
|
|
215
|
+
.set({
|
|
216
|
+
key: value.key,
|
|
217
|
+
start: value.start,
|
|
218
|
+
prefix: value.prefix,
|
|
219
|
+
expiresAt: value.expiresAt,
|
|
220
|
+
createdAt: value.createdAt,
|
|
221
|
+
updatedAt: value.updatedAt,
|
|
222
|
+
})
|
|
223
|
+
.where('id', '=', keyId)
|
|
224
|
+
.execute();
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
await this.remove(fresh.id);
|
|
228
|
+
}
|
|
229
|
+
return {
|
|
230
|
+
key: viewOf(await this.requireRow(userId, keyId)),
|
|
231
|
+
secret: fresh.key,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Replaces a key's scope. `identity` is whoever chooses it: each record a group is limited to must be one they may
|
|
236
|
+
* see. The caller decides who may change a key and whether the new scope is one they may give. A key without a scope
|
|
237
|
+
* cannot be given one this way, nor the reverse.
|
|
238
|
+
*/
|
|
239
|
+
async setScope(userId, keyId, input, identity) {
|
|
240
|
+
const row = await this.requireRow(userId, keyId);
|
|
241
|
+
if (decodeKeyScope(row.permissions) === null)
|
|
242
|
+
throw new ApiKeyRequestError(400, 'KEY_NOT_SCOPED', 'This key has no scope to change.');
|
|
243
|
+
const scope = this.options.scopes.validate(input);
|
|
244
|
+
await this.checkObjects(scope, identity);
|
|
245
|
+
await this.options
|
|
246
|
+
.connection()
|
|
247
|
+
.query.updateTable('apikey')
|
|
248
|
+
.set({ permissions: JSON.stringify(encodeKeyScope(scope)) })
|
|
249
|
+
.where('id', '=', keyId)
|
|
250
|
+
.execute();
|
|
251
|
+
return viewOf(await this.requireRow(userId, keyId));
|
|
252
|
+
}
|
|
253
|
+
/** Renames a key or changes its description; a field left out stays. */
|
|
254
|
+
async update(userId, keyId, input) {
|
|
255
|
+
const row = await this.requireRow(userId, keyId);
|
|
256
|
+
const body = isRecord(input) ? input : {};
|
|
257
|
+
const name = body.name === undefined
|
|
258
|
+
? row.name
|
|
259
|
+
: text(body.name, 'name', MAX_NAME, true);
|
|
260
|
+
const description = body.description === undefined
|
|
261
|
+
? descriptionOf(row.metadata)
|
|
262
|
+
: text(body.description, 'description', MAX_DESCRIPTION, false);
|
|
263
|
+
await this.options
|
|
264
|
+
.connection()
|
|
265
|
+
.query.updateTable('apikey')
|
|
266
|
+
.set({
|
|
267
|
+
name,
|
|
268
|
+
metadata: description ? JSON.stringify({ description }) : null,
|
|
269
|
+
})
|
|
270
|
+
.where('id', '=', keyId)
|
|
271
|
+
.execute();
|
|
272
|
+
return viewOf(await this.requireRow(userId, keyId));
|
|
273
|
+
}
|
|
274
|
+
async revoke(userId, keyId) {
|
|
275
|
+
await this.requireRow(userId, keyId);
|
|
276
|
+
await this.remove(keyId);
|
|
277
|
+
}
|
|
278
|
+
/** Every key of `userId`, as when the account is deleted. */
|
|
279
|
+
async revokeAll(userId) {
|
|
280
|
+
await this.options
|
|
281
|
+
.connection()
|
|
282
|
+
.query.deleteFrom('apikey')
|
|
283
|
+
.where('referenceId', '=', userId)
|
|
284
|
+
.where('configId', '=', 'default')
|
|
285
|
+
.execute();
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* The scope of the key a request authenticated with: compiled from its stored scope, unbounded for a service
|
|
289
|
+
* account's unscoped key, and null for a session or a person's unscoped key. Read once per request.
|
|
290
|
+
*/
|
|
291
|
+
resolve(session, request) {
|
|
292
|
+
const known = this.resolved.get(request);
|
|
293
|
+
if (known)
|
|
294
|
+
return known;
|
|
295
|
+
const result = this.lookup(session, request);
|
|
296
|
+
this.resolved.set(request, result);
|
|
297
|
+
return result;
|
|
298
|
+
}
|
|
299
|
+
async lookup(session, request) {
|
|
300
|
+
// Better Auth's key session carries the key as its token and the key's id as its id; a cookie session never does.
|
|
301
|
+
if (!isApiKeySession(session, request.headers, [API_KEY_HEADER]))
|
|
302
|
+
return null;
|
|
303
|
+
const row = await this.options
|
|
304
|
+
.connection()
|
|
305
|
+
.query.selectFrom('apikey')
|
|
306
|
+
.select(['id', 'permissions'])
|
|
307
|
+
.where('id', '=', session.session.id)
|
|
308
|
+
.executeTakeFirst();
|
|
309
|
+
if (!row)
|
|
310
|
+
return null;
|
|
311
|
+
const scope = decodeKeyScope(row.permissions);
|
|
312
|
+
if (scope)
|
|
313
|
+
return this.options.scopes.compile(row.id, scope);
|
|
314
|
+
return isServiceAccount(session.user)
|
|
315
|
+
? this.options.scopes.unbounded(row.id)
|
|
316
|
+
: null;
|
|
317
|
+
}
|
|
318
|
+
async issue(userId, input) {
|
|
319
|
+
const endpoints = this.options.auth.pluginApi('api-key');
|
|
320
|
+
const created = await endpoints.createApiKey({
|
|
321
|
+
body: {
|
|
322
|
+
userId,
|
|
323
|
+
name: input.name,
|
|
324
|
+
...(input.expiresInDays === null
|
|
325
|
+
? {}
|
|
326
|
+
: { expiresIn: input.expiresInDays * DAY_SECONDS }),
|
|
327
|
+
...(input.scope ? { permissions: encodeKeyScope(input.scope) } : {}),
|
|
328
|
+
},
|
|
329
|
+
});
|
|
330
|
+
// Written directly rather than through Better Auth, whose `metadata` stays off (`enableMetadata`) so that a key's
|
|
331
|
+
// holder cannot write to it over HTTP.
|
|
332
|
+
if (input.description)
|
|
333
|
+
await this.options
|
|
334
|
+
.connection()
|
|
335
|
+
.query.updateTable('apikey')
|
|
336
|
+
.set({ metadata: JSON.stringify({ description: input.description }) })
|
|
337
|
+
.where('id', '=', created.id)
|
|
338
|
+
.execute();
|
|
339
|
+
const row = await this.requireRow(userId, created.id);
|
|
340
|
+
return { key: viewOf(row), secret: created.key };
|
|
341
|
+
}
|
|
342
|
+
async remove(keyId) {
|
|
343
|
+
const endpoints = this.options.auth.pluginApi('api-key');
|
|
344
|
+
await endpoints.deleteServerApiKey({
|
|
345
|
+
body: { keyId, configId: 'default' },
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
async requireRow(userId, keyId) {
|
|
349
|
+
const row = await this.options
|
|
350
|
+
.connection()
|
|
351
|
+
.query.selectFrom('apikey')
|
|
352
|
+
.selectAll()
|
|
353
|
+
.where('id', '=', keyId)
|
|
354
|
+
.where('referenceId', '=', userId)
|
|
355
|
+
.where('configId', '=', 'default')
|
|
356
|
+
.executeTakeFirst();
|
|
357
|
+
if (!row)
|
|
358
|
+
throw new ApiKeyRequestError(404, 'KEY_NOT_FOUND', 'API key not found.');
|
|
359
|
+
return row;
|
|
360
|
+
}
|
|
361
|
+
async checkObjects(scope, identity) {
|
|
362
|
+
for (const [groupId, grant] of Object.entries(scope.groups)) {
|
|
363
|
+
const picked = pickedObjects(grant);
|
|
364
|
+
if (!picked)
|
|
365
|
+
continue;
|
|
366
|
+
const source = this.options.scopes.groups.objects(groupId);
|
|
367
|
+
const found = new Set((source ? await source.list({ identity, ids: picked }) : []).map((item) => item.id));
|
|
368
|
+
const missing = picked.filter((id) => !found.has(id));
|
|
369
|
+
if (missing.length > 0)
|
|
370
|
+
throw new ApiKeyScopeError('UNKNOWN_SCOPE_OBJECT', `${groupId} has no record ${missing.join(', ')} you may choose.`);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
expiryOf(value, scoped) {
|
|
374
|
+
const max = scoped ? this.maxScopedKeyDays : null;
|
|
375
|
+
if (value === null || value === undefined) {
|
|
376
|
+
if (max !== null)
|
|
377
|
+
throw new ApiKeyRequestError(400, 'EXPIRY_REQUIRED', `A scoped key expires within ${max} days.`);
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
if (typeof value !== 'number' ||
|
|
381
|
+
!Number.isInteger(value) ||
|
|
382
|
+
value < 1 ||
|
|
383
|
+
value > 365 ||
|
|
384
|
+
(max !== null && value > max))
|
|
385
|
+
throw new ApiKeyRequestError(400, 'INVALID_EXPIRY', `expiresInDays must be a whole number of days from 1 to ${max ?? 365}, or null.`);
|
|
386
|
+
return value;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
function isRecord(value) {
|
|
390
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
391
|
+
}
|
|
392
|
+
function text(value, name, max, required) {
|
|
393
|
+
if (value === undefined || value === null || value === '') {
|
|
394
|
+
if (required)
|
|
395
|
+
throw new ApiKeyRequestError(400, 'INVALID_KEY', `${name} is required.`);
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
if (typeof value !== 'string' || value.trim().length > max)
|
|
399
|
+
throw new ApiKeyRequestError(400, 'INVALID_KEY', `${name} must be text of at most ${max} characters.`);
|
|
400
|
+
const trimmed = value.trim();
|
|
401
|
+
if (!trimmed && required)
|
|
402
|
+
throw new ApiKeyRequestError(400, 'INVALID_KEY', `${name} is required.`);
|
|
403
|
+
return trimmed || null;
|
|
404
|
+
}
|
|
405
|
+
function parseDate(value) {
|
|
406
|
+
if (value instanceof Date)
|
|
407
|
+
return value;
|
|
408
|
+
if (typeof value === 'number' || typeof value === 'bigint')
|
|
409
|
+
return new Date(Number(value));
|
|
410
|
+
if (typeof value === 'string') {
|
|
411
|
+
const numeric = /^-?\d+(?:\.\d+)?$/u.test(value.trim());
|
|
412
|
+
const date = new Date(numeric ? Number(value) : value);
|
|
413
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
414
|
+
}
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
function iso(value) {
|
|
418
|
+
return parseDate(value)?.toISOString() ?? null;
|
|
419
|
+
}
|
|
420
|
+
function descriptionOf(metadata) {
|
|
421
|
+
let value = metadata;
|
|
422
|
+
if (typeof value === 'string') {
|
|
423
|
+
try {
|
|
424
|
+
value = JSON.parse(value);
|
|
425
|
+
// Better Auth may store the object stringified twice.
|
|
426
|
+
if (typeof value === 'string')
|
|
427
|
+
value = JSON.parse(value);
|
|
428
|
+
}
|
|
429
|
+
catch {
|
|
430
|
+
return null;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
const description = isRecord(value) ? value.description : undefined;
|
|
434
|
+
return typeof description === 'string' && description ? description : null;
|
|
435
|
+
}
|
|
436
|
+
function viewOf(row) {
|
|
437
|
+
return {
|
|
438
|
+
id: row.id,
|
|
439
|
+
name: row.name,
|
|
440
|
+
description: descriptionOf(row.metadata),
|
|
441
|
+
start: row.start,
|
|
442
|
+
enabled: typeof row.enabled === 'boolean'
|
|
443
|
+
? row.enabled
|
|
444
|
+
: Number(row.enabled) === 1,
|
|
445
|
+
createdAt: iso(row.createdAt) ?? new Date(0).toISOString(),
|
|
446
|
+
expiresAt: iso(row.expiresAt),
|
|
447
|
+
lastUsedAt: iso(row.lastRequest),
|
|
448
|
+
scope: decodeKeyScope(row.permissions),
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
//# sourceMappingURL=scoped-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoped-keys.js","sourceRoot":"","sources":["../../server/scoped-keys.ts"],"names":[],"mappings":"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"}
|