@north-light/identity 0.3.438 → 0.3.440
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/dist/index.d.ts +29 -1
- package/dist/index.js +25 -2
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export interface IdTokenClaims extends JWTPayload {
|
|
|
22
22
|
family_name?: string;
|
|
23
23
|
picture?: string;
|
|
24
24
|
}
|
|
25
|
-
export type Scope = 'crtr:llm' | 'crtr:act' | 'crtr:schedule' | `crtr:memory:${'read' | 'rw'}:user${'' | `:${string}`}` | 'crtr:memory:manage:user' | `crtr:memory:${'read' | 'rw'}:app:${string}` | `crtr:files:${'read' | 'rw'}:${'user' | `app:${string}`}:${string}` | 'crtr:files:share' | `crtr:${'conversations' | 'objects'}:read:app:${string}` | `crtr:peer:${string}` | `${string}:${string}`;
|
|
25
|
+
export type Scope = 'crtr:llm' | 'crtr:act' | 'crtr:schedule' | `crtr:memory:${'read' | 'rw'}:user${'' | `:${string}`}` | 'crtr:memory:manage:user' | `crtr:memory:${'read' | 'rw'}:app:${string}` | `crtr:files:${'read' | 'rw'}:${'user' | `app:${string}`}:${string}` | 'crtr:files:share' | `crtr:${'conversations' | 'objects'}:read:app:${string}` | `crtr:objects:${'message' | 'spawn'}:app:${string}` | `crtr:peer:${string}` | `${string}:${string}`;
|
|
26
26
|
/** App-memory form keys omit the app id. */
|
|
27
27
|
export declare const ENFORCED: ReadonlySet<string>;
|
|
28
28
|
export declare function parseScope(value: string, grantee?: string): Scope;
|
|
@@ -73,6 +73,34 @@ export declare function verifyAccessToken(options: {
|
|
|
73
73
|
issuer: string;
|
|
74
74
|
audience: string;
|
|
75
75
|
}): Promise<AccessTokenClaims>;
|
|
76
|
+
/** The claims of a machine token: one machine of an account calling another (or the account relay). It names the
|
|
77
|
+
* person and the calling machine and carries no grant, so it authorizes nothing on its own. */
|
|
78
|
+
export interface MachineTokenClaims extends JWTPayload {
|
|
79
|
+
iss: string;
|
|
80
|
+
/** The single audience: a peer machine URL or the relay origin. */
|
|
81
|
+
aud: string;
|
|
82
|
+
/** The account's person, `user:<id>`. */
|
|
83
|
+
sub: string;
|
|
84
|
+
/** Always equal to `sub`. */
|
|
85
|
+
grantee: string;
|
|
86
|
+
client_id: string;
|
|
87
|
+
/** The calling machine, `runtime:<id>`. */
|
|
88
|
+
machine_id: string;
|
|
89
|
+
exp: number;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Verifies a machine token: ES256 with typ `at+jwt`, signature against `jwks`, `iss` = `issuer`, `aud` a string equal
|
|
93
|
+
* to `audience` (the sole audience), and `exp`. `sub` must be `user:<id>`, `grantee` must equal `sub`, `machine_id`
|
|
94
|
+
* must be `runtime:<id>` and `client_id` a non-empty string. A token carrying a `grant`, `rev` or `scope` claim is
|
|
95
|
+
* refused, so an app grant token never verifies here; `verifyAccessToken` requires an `app:` grantee, so a machine
|
|
96
|
+
* token never verifies there.
|
|
97
|
+
*/
|
|
98
|
+
export declare function verifyMachineToken(options: {
|
|
99
|
+
token: string;
|
|
100
|
+
jwks: JSONWebKeySet | JwksCache;
|
|
101
|
+
issuer: string;
|
|
102
|
+
audience: string;
|
|
103
|
+
}): Promise<MachineTokenClaims>;
|
|
76
104
|
/** One level of the outbound token's RFC 8693 `act` nesting: the actor, and the actor it acted for. */
|
|
77
105
|
export interface OutboundActor {
|
|
78
106
|
sub: string;
|
package/dist/index.js
CHANGED
|
@@ -31,9 +31,10 @@ function selector(value) {
|
|
|
31
31
|
match = /^crtr:files:(read|rw):(user|app:[A-Za-z0-9_-]{1,64}):(.+)$/.exec(value);
|
|
32
32
|
if (match && validPath(match[3], true))
|
|
33
33
|
return { kind: 'files', access: match[1], holder: match[2], path: match[3] };
|
|
34
|
-
|
|
34
|
+
// read, message and spawn are three unrelated scopes: `covers` is exact equality for them.
|
|
35
|
+
match = /^crtr:(?:(conversations):read|(objects):(?:read|message|spawn)):app:([A-Za-z0-9_-]{1,64})$/.exec(value);
|
|
35
36
|
if (match)
|
|
36
|
-
return { kind: match[1], value };
|
|
37
|
+
return { kind: (match[1] ?? match[2]), value };
|
|
37
38
|
match = /^crtr:peer:([A-Za-z0-9_-]{1,64})$/.exec(value);
|
|
38
39
|
if (match)
|
|
39
40
|
return { kind: 'peer', value };
|
|
@@ -226,6 +227,28 @@ export async function verifyAccessToken(options) {
|
|
|
226
227
|
throw new Error('Invalid access token claims');
|
|
227
228
|
return payload;
|
|
228
229
|
}
|
|
230
|
+
/**
|
|
231
|
+
* Verifies a machine token: ES256 with typ `at+jwt`, signature against `jwks`, `iss` = `issuer`, `aud` a string equal
|
|
232
|
+
* to `audience` (the sole audience), and `exp`. `sub` must be `user:<id>`, `grantee` must equal `sub`, `machine_id`
|
|
233
|
+
* must be `runtime:<id>` and `client_id` a non-empty string. A token carrying a `grant`, `rev` or `scope` claim is
|
|
234
|
+
* refused, so an app grant token never verifies here; `verifyAccessToken` requires an `app:` grantee, so a machine
|
|
235
|
+
* token never verifies there.
|
|
236
|
+
*/
|
|
237
|
+
export async function verifyMachineToken(options) {
|
|
238
|
+
const header = decodeProtectedHeader(options.token);
|
|
239
|
+
if (header.typ !== 'at+jwt' || header.alg !== 'ES256')
|
|
240
|
+
throw new Error('Invalid machine token header');
|
|
241
|
+
const keys = await keySet(options.jwks, header.kid);
|
|
242
|
+
const { payload } = await jwtVerify(options.token, createLocalJWKSet(keys), {
|
|
243
|
+
issuer: options.issuer, audience: options.audience, algorithms: ['ES256'], typ: 'at+jwt', requiredClaims: ['exp'],
|
|
244
|
+
});
|
|
245
|
+
if (payload.aud !== options.audience || !validatePrincipal(payload.sub, 'user') || payload.grantee !== payload.sub ||
|
|
246
|
+
!validatePrincipal(payload.machine_id, 'runtime') || !nonEmptyString(payload.client_id) || typeof payload.exp !== 'number' ||
|
|
247
|
+
payload.grant !== undefined || payload.rev !== undefined || payload.scope !== undefined) {
|
|
248
|
+
throw new Error('Invalid machine token claims');
|
|
249
|
+
}
|
|
250
|
+
return payload;
|
|
251
|
+
}
|
|
229
252
|
function nonEmptyString(value) {
|
|
230
253
|
return typeof value === 'string' && value !== '';
|
|
231
254
|
}
|