@toa.io/extensions.exposition 1.0.0-alpha.302 → 1.0.0-alpha.304
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/components/identity.basic/types/toa.d.ts +1 -1
- package/components/identity.clients/types/toa.d.ts +1 -1
- package/components/identity.federation/types/toa.d.ts +1 -1
- package/components/identity.grants/manifest.toa.yaml +3 -1
- package/components/identity.grants/types/toa.d.ts +1 -1
- package/components/identity.otp/types/toa.d.ts +1 -1
- package/components/identity.passkeys/types/toa.d.ts +1 -1
- package/components/identity.tokens/operations/decrypt.js +106 -60
- package/components/identity.tokens/operations/lib/jose.js +5 -2
- package/components/identity.tokens/source/decrypt.ts +136 -65
- package/components/identity.tokens/source/lib/jose.js +5 -1
- package/components/identity.tokens/types/index.d.ts +1 -0
- package/components/identity.tokens/types/toa.d.ts +1 -1
- package/package.json +7 -7
- package/transpiled/Directive.d.ts +11 -4
- package/transpiled/Directive.js +50 -14
- package/transpiled/Directive.js.map +1 -1
- package/transpiled/Endpoint.js +13 -11
- package/transpiled/Endpoint.js.map +1 -1
- package/transpiled/Gateway.js +4 -0
- package/transpiled/Gateway.js.map +1 -1
- package/transpiled/HTTP/Context.d.ts +17 -0
- package/transpiled/HTTP/Context.js +17 -0
- package/transpiled/HTTP/Context.js.map +1 -1
- package/transpiled/HTTP/Server.js +12 -6
- package/transpiled/HTTP/Server.js.map +1 -1
- package/transpiled/HTTP/messages.d.ts +9 -7
- package/transpiled/HTTP/messages.js +15 -2
- package/transpiled/HTTP/messages.js.map +1 -1
- package/transpiled/HTTP/types.d.ts +1 -0
- package/transpiled/MCP/tools.js +66 -31
- package/transpiled/MCP/tools.js.map +1 -1
- package/transpiled/Query.js +2 -0
- package/transpiled/Query.js.map +1 -1
- package/transpiled/RTD/Directives.d.ts +26 -8
- package/transpiled/RTD/Match.d.ts +6 -0
- package/transpiled/RTD/Method.d.ts +12 -0
- package/transpiled/RTD/Method.js +21 -1
- package/transpiled/RTD/Method.js.map +1 -1
- package/transpiled/RTD/Node.d.ts +3 -1
- package/transpiled/RTD/Node.js +5 -3
- package/transpiled/RTD/Node.js.map +1 -1
- package/transpiled/RTD/Route.d.ts +1 -1
- package/transpiled/RTD/Route.js +8 -5
- package/transpiled/RTD/Route.js.map +1 -1
- package/transpiled/RTD/Tree.d.ts +12 -0
- package/transpiled/RTD/Tree.js +19 -1
- package/transpiled/RTD/Tree.js.map +1 -1
- package/transpiled/RTD/segment.d.ts +2 -0
- package/transpiled/RTD/segment.js +15 -0
- package/transpiled/RTD/segment.js.map +1 -1
- package/transpiled/directives/auth/Authorization.d.ts +9 -7
- package/transpiled/directives/auth/Authorization.js +17 -16
- package/transpiled/directives/auth/Authorization.js.map +1 -1
- package/transpiled/directives/cache/Cache.d.ts +11 -0
- package/transpiled/directives/cache/Cache.js +23 -24
- package/transpiled/directives/cache/Cache.js.map +1 -1
- package/transpiled/directives/cache/etag.d.ts +10 -7
- package/transpiled/directives/cache/etag.js +13 -10
- package/transpiled/directives/cache/etag.js.map +1 -1
- package/transpiled/directives/cors/CORS.js +1 -1
- package/transpiled/directives/cors/CORS.js.map +1 -1
- package/transpiled/directives/flow/Compose.js +2 -0
- package/transpiled/directives/flow/Compose.js.map +1 -1
- package/transpiled/directives/help/Family.d.ts +1 -2
- package/transpiled/directives/help/Family.js +1 -1
- package/transpiled/directives/help/Family.js.map +1 -1
- package/transpiled/directives/io/IO.d.ts +1 -1
- package/transpiled/directives/io/IO.js +1 -1
- package/transpiled/directives/io/IO.js.map +1 -1
- package/transpiled/directives/io/Output.d.ts +5 -3
- package/transpiled/directives/io/Output.js +11 -35
- package/transpiled/directives/io/Output.js.map +1 -1
- package/transpiled/directives/io/Status.d.ts +1 -1
- package/transpiled/directives/io/Status.js +4 -2
- package/transpiled/directives/io/Status.js.map +1 -1
- package/transpiled/directives/map/Map.d.ts +1 -1
- package/transpiled/directives/map/Map.js +1 -1
- package/transpiled/directives/map/Map.js.map +1 -1
- package/transpiled/directives/mcp/MCP.d.ts +1 -2
- package/transpiled/directives/mcp/MCP.js +1 -1
- package/transpiled/directives/mcp/MCP.js.map +1 -1
- package/transpiled/directives/octets/Octets.d.ts +1 -1
- package/transpiled/directives/octets/Octets.js +1 -1
- package/transpiled/directives/octets/Octets.js.map +1 -1
- package/transpiled/measurements.d.ts +22 -0
- package/transpiled/measurements.js +37 -0
- package/transpiled/measurements.js.map +1 -0
- package/transpiled/service.js +22 -2
- package/transpiled/service.js.map +1 -1
- package/ui/dist/_app/immutable/chunks/{Wl536IQX.js → BI21DxGX.js} +1 -1
- package/ui/dist/_app/immutable/chunks/{CyQvDdUS.js → B_XBOx9b.js} +1 -1
- package/ui/dist/_app/immutable/chunks/{BNmwbB_m.js → D9-CL3SX.js} +2 -2
- package/ui/dist/_app/immutable/chunks/{D8WVrjO4.js → DfeVAkjY.js} +1 -1
- package/ui/dist/_app/immutable/entry/{app.BnIDHdVY.js → app.BG2uapp5.js} +2 -2
- package/ui/dist/_app/immutable/entry/start.Bnttjc6A.js +1 -0
- package/ui/dist/_app/immutable/nodes/{0.DV2orh1u.js → 0.CAhVptPP.js} +1 -1
- package/ui/dist/_app/immutable/nodes/{1.Bgonurdo.js → 1.CymYf6vY.js} +1 -1
- package/ui/dist/_app/immutable/nodes/{2.C0ZHj2rR.js → 2.DtwEKRzb.js} +1 -1
- package/ui/dist/_app/immutable/nodes/{3.DOixCoug.js → 3.BgfGYNeS.js} +1 -1
- package/ui/dist/_app/immutable/nodes/{4.fXuZ_LUX.js → 4.B7W24tJ1.js} +1 -1
- package/ui/dist/_app/immutable/nodes/{5.BN65yDZR.js → 5.FCfJU5jO.js} +1 -1
- package/ui/dist/_app/immutable/nodes/{6.gez_DiIA.js → 6.B9oqMcPQ.js} +1 -1
- package/ui/dist/_app/version.json +1 -1
- package/ui/dist/index.html +10 -10
- package/ui/dist/_app/immutable/entry/start.BhKXzsOH.js +0 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type { Options, Query, RemoteError } from '@toa.io/core/types'
|
|
5
5
|
import type { Secret } from '@toa.io/extensions.configuration'
|
|
6
6
|
import type { FetchInit } from '@toa.io/extensions.fetch'
|
|
7
|
-
import type { Logs, Span } from '@toa.io/extensions.telemetry'
|
|
7
|
+
import type { Logs, Metrics, Span } from '@toa.io/extensions.telemetry'
|
|
8
8
|
import type { Readable } from 'node:stream'
|
|
9
9
|
|
|
10
10
|
export interface Entity {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type { Options, Query, RemoteError } from '@toa.io/core/types'
|
|
5
5
|
import type { FetchInit } from '@toa.io/extensions.fetch'
|
|
6
6
|
import type { Stash } from '@toa.io/extensions.stash'
|
|
7
|
-
import type { Logs, Span } from '@toa.io/extensions.telemetry'
|
|
7
|
+
import type { Logs, Metrics, Span } from '@toa.io/extensions.telemetry'
|
|
8
8
|
import type { Readable } from 'node:stream'
|
|
9
9
|
|
|
10
10
|
export interface Entity {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type { Options, Query, RemoteError } from '@toa.io/core/types'
|
|
5
5
|
import type { Secret } from '@toa.io/extensions.configuration'
|
|
6
6
|
import type { FetchInit } from '@toa.io/extensions.fetch'
|
|
7
|
-
import type { Logs, Span } from '@toa.io/extensions.telemetry'
|
|
7
|
+
import type { Logs, Metrics, Span } from '@toa.io/extensions.telemetry'
|
|
8
8
|
import type { Readable } from 'node:stream'
|
|
9
9
|
|
|
10
10
|
export interface Entity {
|
|
@@ -231,7 +231,9 @@ exposition:
|
|
|
231
231
|
endpoint: list
|
|
232
232
|
POST:
|
|
233
233
|
io:input: [client, redirect, challenge, method, scope, resource]
|
|
234
|
-
io:
|
|
234
|
+
# `status` is read by `io:status` out of what the operation answers, and taken out of the
|
|
235
|
+
# body before it is sent
|
|
236
|
+
io:output: [code, expires_in, error, error_description, status]
|
|
235
237
|
io:status: status
|
|
236
238
|
cache:exact: no-store
|
|
237
239
|
endpoint: authorize
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type { Options, Query, RemoteError } from '@toa.io/core/types'
|
|
5
5
|
import type { FetchInit } from '@toa.io/extensions.fetch'
|
|
6
6
|
import type { Stash } from '@toa.io/extensions.stash'
|
|
7
|
-
import type { Logs, Span } from '@toa.io/extensions.telemetry'
|
|
7
|
+
import type { Logs, Metrics, Span } from '@toa.io/extensions.telemetry'
|
|
8
8
|
import type { Readable } from 'node:stream'
|
|
9
9
|
|
|
10
10
|
export interface Entity {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type { Options, Query, RemoteError } from '@toa.io/core/types'
|
|
5
5
|
import type { FetchInit } from '@toa.io/extensions.fetch'
|
|
6
6
|
import type { Stash } from '@toa.io/extensions.stash'
|
|
7
|
-
import type { Logs, Span } from '@toa.io/extensions.telemetry'
|
|
7
|
+
import type { Logs, Metrics, Span } from '@toa.io/extensions.telemetry'
|
|
8
8
|
import type { Readable } from 'node:stream'
|
|
9
9
|
|
|
10
10
|
export interface Entity {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type { Options, Query, RemoteError } from '@toa.io/core/types'
|
|
5
5
|
import type { FetchInit } from '@toa.io/extensions.fetch'
|
|
6
6
|
import type { Stash } from '@toa.io/extensions.stash'
|
|
7
|
-
import type { Logs, Span } from '@toa.io/extensions.telemetry'
|
|
7
|
+
import type { Logs, Metrics, Span } from '@toa.io/extensions.telemetry'
|
|
8
8
|
import type { Readable } from 'node:stream'
|
|
9
9
|
|
|
10
10
|
export interface Entity {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { createDecipheriv } from 'node:crypto';
|
|
1
2
|
import { DecryptFactory, ImportKeyFactory } from 'paseto/v3/local';
|
|
2
3
|
import { LRUCache } from 'lru-cache';
|
|
3
4
|
import { form, jweKey } from './lib/index.js';
|
|
4
|
-
import { load } from './lib/jose.js';
|
|
5
5
|
export class Computation {
|
|
6
6
|
keys = {};
|
|
7
7
|
legacy = {};
|
|
@@ -23,32 +23,29 @@ export class Computation {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
async execute(token) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
if (form(token) === 'paseto') {
|
|
27
|
+
const kid = this.pasetoKid(token);
|
|
28
|
+
if (kid instanceof Error)
|
|
29
|
+
return kid;
|
|
30
|
+
const key = await this.key(kid, true);
|
|
31
|
+
if (key instanceof Error)
|
|
32
|
+
return key;
|
|
33
|
+
const claims = await decryptPaseto(token, key.key);
|
|
34
|
+
if (claims instanceof Error)
|
|
35
|
+
return claims;
|
|
36
|
+
// a token of the form this component leaves behind is answered with a re-issue
|
|
37
|
+
return this.answer(claims, key, true);
|
|
38
|
+
}
|
|
39
|
+
const jwe = parse(token);
|
|
40
|
+
if (jwe instanceof Error)
|
|
41
|
+
return jwe;
|
|
42
|
+
const key = await this.key(jwe.kid, false);
|
|
31
43
|
if (key instanceof Error)
|
|
32
44
|
return key;
|
|
33
|
-
const claims =
|
|
34
|
-
? await decryptPaseto(token, key.key)
|
|
35
|
-
: await decryptJWE(token, key.key);
|
|
45
|
+
const claims = open(jwe, key.key);
|
|
36
46
|
if (claims instanceof Error)
|
|
37
47
|
return claims;
|
|
38
|
-
this.
|
|
39
|
-
if (key.identity !== undefined && claims.identity.id !== key.identity)
|
|
40
|
-
return ERR_FORGED_KEY;
|
|
41
|
-
if (key.revokedAt !== undefined)
|
|
42
|
-
return ERR_REVOKED_KEY;
|
|
43
|
-
return {
|
|
44
|
-
iss: claims.iss,
|
|
45
|
-
iat: claims.iat,
|
|
46
|
-
exp: claims.exp,
|
|
47
|
-
identity: claims.identity,
|
|
48
|
-
...(claims.aud === undefined ? {} : { aud: claims.aud }),
|
|
49
|
-
refresh: legacy || (kid !== this.latest && key.identity === undefined),
|
|
50
|
-
custom: key.identity !== undefined
|
|
51
|
-
};
|
|
48
|
+
return this.answer(claims, key, jwe.kid !== this.latest && key.identity === undefined);
|
|
52
49
|
}
|
|
53
50
|
pasetoKid(token) {
|
|
54
51
|
const [, , , footer] = token.split('.');
|
|
@@ -65,20 +62,22 @@ export class Computation {
|
|
|
65
62
|
return ERR_INVALID_TOKEN;
|
|
66
63
|
}
|
|
67
64
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
65
|
+
/** What both forms answer once their claims are open. */
|
|
66
|
+
answer(claims, key, refresh) {
|
|
67
|
+
this.logs.debug('Token claims', claims);
|
|
68
|
+
if (key.identity !== undefined && claims.identity.id !== key.identity)
|
|
69
|
+
return ERR_FORGED_KEY;
|
|
70
|
+
if (key.revokedAt !== undefined)
|
|
71
|
+
return ERR_REVOKED_KEY;
|
|
72
|
+
return {
|
|
73
|
+
iss: claims.iss,
|
|
74
|
+
iat: claims.iat,
|
|
75
|
+
exp: claims.exp,
|
|
76
|
+
identity: claims.identity,
|
|
77
|
+
...(claims.aud === undefined ? {} : { aud: claims.aud }),
|
|
78
|
+
refresh,
|
|
79
|
+
custom: key.identity !== undefined
|
|
80
|
+
};
|
|
82
81
|
}
|
|
83
82
|
async key(kid, legacy) {
|
|
84
83
|
const configured = legacy ? this.legacy : this.keys;
|
|
@@ -103,34 +102,81 @@ async function decryptPaseto(token, key) {
|
|
|
103
102
|
return ERR_INVALID_TOKEN;
|
|
104
103
|
}
|
|
105
104
|
}
|
|
106
|
-
|
|
105
|
+
/**
|
|
106
|
+
* The five parts of a compact JWE (RFC 7516), of the one form this component issues: `dir`, so
|
|
107
|
+
* the encrypted key is empty, `A256GCM`, and a `kid` naming the key. A header that asks for
|
|
108
|
+
* anything else — another algorithm, a critical extension, compression — is refused, as jose
|
|
109
|
+
* refuses it.
|
|
110
|
+
*/
|
|
111
|
+
function parse(token) {
|
|
112
|
+
const parts = token.split('.');
|
|
113
|
+
if (parts.length !== PARTS || parts[1] !== '')
|
|
114
|
+
return ERR_INVALID_TOKEN;
|
|
115
|
+
const [header, , iv, ciphertext, tag] = parts;
|
|
116
|
+
let declared;
|
|
107
117
|
try {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
118
|
+
declared = JSON.parse(Buffer.from(header, 'base64url').toString('utf-8'));
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return ERR_INVALID_TOKEN;
|
|
122
|
+
}
|
|
123
|
+
if (declared === null ||
|
|
124
|
+
typeof declared !== 'object' ||
|
|
125
|
+
declared.alg !== 'dir' ||
|
|
126
|
+
declared.enc !== 'A256GCM' ||
|
|
127
|
+
declared.typ !== 'JWT' ||
|
|
128
|
+
typeof declared.kid !== 'string' ||
|
|
129
|
+
declared.crit !== undefined ||
|
|
130
|
+
declared.zip !== undefined)
|
|
131
|
+
return ERR_INVALID_TOKEN;
|
|
132
|
+
return {
|
|
133
|
+
kid: declared.kid,
|
|
134
|
+
// the header as it was written, which is what it was encrypted against
|
|
135
|
+
aad: Buffer.from(header, 'ascii'),
|
|
136
|
+
iv: Buffer.from(iv, 'base64url'),
|
|
137
|
+
ciphertext: Buffer.from(ciphertext, 'base64url'),
|
|
138
|
+
tag: Buffer.from(tag, 'base64url')
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/** The claims a token carries, where its tag holds and its times admit it. */
|
|
142
|
+
function open(jwe, key) {
|
|
143
|
+
if (jwe.iv.length !== IV || jwe.tag.length !== TAG)
|
|
144
|
+
return ERR_INVALID_TOKEN;
|
|
145
|
+
let payload;
|
|
146
|
+
try {
|
|
147
|
+
const decipher = createDecipheriv('aes-256-gcm', jweKey(key), jwe.iv);
|
|
148
|
+
decipher.setAAD(jwe.aad);
|
|
149
|
+
decipher.setAuthTag(jwe.tag);
|
|
150
|
+
payload = JSON.parse(Buffer.concat([decipher.update(jwe.ciphertext), decipher.final()]).toString('utf-8'));
|
|
129
151
|
}
|
|
130
152
|
catch {
|
|
131
153
|
return ERR_INVALID_TOKEN;
|
|
132
154
|
}
|
|
155
|
+
if (payload === null ||
|
|
156
|
+
typeof payload !== 'object' ||
|
|
157
|
+
typeof payload.iss !== 'string' ||
|
|
158
|
+
typeof payload.iat !== 'number' ||
|
|
159
|
+
typeof payload.identity !== 'object' ||
|
|
160
|
+
payload.identity === null)
|
|
161
|
+
return ERR_INVALID_TOKEN;
|
|
162
|
+
const now = Date.now();
|
|
163
|
+
if (payload.exp !== undefined && payload.exp * 1000 <= now)
|
|
164
|
+
return ERR_INVALID_TOKEN;
|
|
165
|
+
if (payload.nbf !== undefined && payload.nbf * 1000 > now)
|
|
166
|
+
return ERR_INVALID_TOKEN;
|
|
167
|
+
return {
|
|
168
|
+
iss: payload.iss,
|
|
169
|
+
iat: new Date(payload.iat * 1000).toISOString(),
|
|
170
|
+
...(payload.exp === undefined
|
|
171
|
+
? {}
|
|
172
|
+
: { exp: new Date(payload.exp * 1000).toISOString() }),
|
|
173
|
+
identity: payload.identity,
|
|
174
|
+
...(payload.aud === undefined ? {} : { aud: payload.aud })
|
|
175
|
+
};
|
|
133
176
|
}
|
|
177
|
+
const PARTS = 5;
|
|
178
|
+
const IV = 12;
|
|
179
|
+
const TAG = 16;
|
|
134
180
|
const importKey = ImportKeyFactory().run;
|
|
135
181
|
const decryptLocal = DecryptFactory().run;
|
|
136
182
|
const ERR_INVALID_TOKEN = new (class InvalidTokenError extends Error {
|
|
@@ -145,4 +191,4 @@ const ERR_FORGED_KEY = new (class ForgedKeyError extends Error {
|
|
|
145
191
|
const ERR_REVOKED_KEY = new (class RevokedKeyError extends Error {
|
|
146
192
|
code = 'REVOKED_KEY';
|
|
147
193
|
})();
|
|
148
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
194
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjcnlwdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NvdXJjZS9kZWNyeXB0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUM5QyxPQUFPLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDbEUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUNwQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBSzdDLE1BQU0sT0FBTyxXQUFXO0lBQ0wsSUFBSSxHQUF3QixFQUFFLENBQUE7SUFDOUIsTUFBTSxHQUF3QixFQUFFLENBQUE7SUFDekMsS0FBSyxDQUE2QjtJQUNsQyxNQUFNLENBQVM7SUFDZixNQUFNLENBQXdDO0lBQzlDLElBQUksQ0FBa0I7SUFFdkIsS0FBSyxDQUFDLE9BQWdCO1FBQzNCLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLE1BQU0sS0FBSyxRQUFRLENBQUMsQ0FBQTtRQUVuRixJQUFJLE1BQU0sS0FBSyxTQUFTO1lBQ3RCLE1BQU0sSUFBSSxTQUFTLENBQUMseUNBQXlDLENBQUMsQ0FBQTtRQUVoRSxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxFQUFFLENBQUE7UUFDdkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUE7UUFDMUMsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLFFBQVEsQ0FBbUIsT0FBTyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUN4RSxJQUFJLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUE7UUFFeEIsS0FBSyxNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsSUFBSSxPQUFPLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzdELE1BQU0sTUFBTSxHQUFHLE1BQU0sS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUE7WUFFNUQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFBO1FBQ3BDLENBQUM7SUFDSCxDQUFDO0lBRU0sS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFhO1FBQ2hDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQzdCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUE7WUFFakMsSUFBSSxHQUFHLFlBQVksS0FBSztnQkFBRSxPQUFPLEdBQUcsQ0FBQTtZQUVwQyxNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFBO1lBRXJDLElBQUksR0FBRyxZQUFZLEtBQUs7Z0JBQUUsT0FBTyxHQUFHLENBQUE7WUFFcEMsTUFBTSxNQUFNLEdBQUcsTUFBTSxhQUFhLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUVsRCxJQUFJLE1BQU0sWUFBWSxLQUFLO2dCQUFFLE9BQU8sTUFBTSxDQUFBO1lBRTFDLCtFQUErRTtZQUMvRSxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQTtRQUN2QyxDQUFDO1FBRUQsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBRXhCLElBQUksR0FBRyxZQUFZLEtBQUs7WUFBRSxPQUFPLEdBQUcsQ0FBQTtRQUVwQyxNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQTtRQUUxQyxJQUFJLEdBQUcsWUFBWSxLQUFLO1lBQUUsT0FBTyxHQUFHLENBQUE7UUFFcEMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7UUFFakMsSUFBSSxNQUFNLFlBQVksS0FBSztZQUFFLE9BQU8sTUFBTSxDQUFBO1FBRTFDLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FDaEIsTUFBTSxFQUNOLEdBQUcsRUFDSCxHQUFHLENBQUMsR0FBRyxLQUFLLElBQUksQ0FBQyxNQUFNLElBQUksR0FBRyxDQUFDLFFBQVEsS0FBSyxTQUFTLENBQ3RELENBQUE7SUFDSCxDQUFDO0lBRU8sU0FBUyxDQUFDLEtBQWE7UUFDN0IsTUFBTSxDQUFDLEVBQUUsQUFBRCxFQUFHLEFBQUQsRUFBRyxNQUFNLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBRXZDLElBQUksTUFBTSxLQUFLLFNBQVM7WUFBRSxPQUFPLGlCQUFpQixDQUFBO1FBRWxELElBQUksQ0FBQztZQUNILE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQTtZQUMvRCxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQTtZQUVoQyxJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVE7Z0JBQUUsT0FBTyxpQkFBaUIsQ0FBQTtZQUVyRCxPQUFPLEdBQUcsQ0FBQTtRQUNaLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxPQUFPLGlCQUFpQixDQUFBO1FBQzFCLENBQUM7SUFDSCxDQUFDO0lBRUQseURBQXlEO0lBQ2pELE1BQU0sQ0FBQyxNQUFjLEVBQUUsR0FBUSxFQUFFLE9BQWdCO1FBQ3ZELElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGNBQWMsRUFBRSxNQUFNLENBQUMsQ0FBQTtRQUV2QyxJQUFJLEdBQUcsQ0FBQyxRQUFRLEtBQUssU0FBUyxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxLQUFLLEdBQUcsQ0FBQyxRQUFRO1lBQ25FLE9BQU8sY0FBYyxDQUFBO1FBRXZCLElBQUksR0FBRyxDQUFDLFNBQVMsS0FBSyxTQUFTO1lBQUUsT0FBTyxlQUFlLENBQUE7UUFFdkQsT0FBTztZQUNMLEdBQUcsRUFBRSxNQUFNLENBQUMsR0FBRztZQUNmLEdBQUcsRUFBRSxNQUFNLENBQUMsR0FBRztZQUNmLEdBQUcsRUFBRSxNQUFNLENBQUMsR0FBRztZQUNmLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUTtZQUN6QixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ3hELE9BQU87WUFDUCxNQUFNLEVBQUUsR0FBRyxDQUFDLFFBQVEsS0FBSyxTQUFTO1NBQ25DLENBQUE7SUFDSCxDQUFDO0lBRU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFXLEVBQUUsTUFBZTtRQUM1QyxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUE7UUFFbkQsSUFBSSxHQUFHLElBQUksVUFBVTtZQUFFLE9BQU8sVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBRTdDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3pCLE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFBO1lBRS9ELElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUE7UUFDaEMsQ0FBQztRQUVELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBRWpDLE9BQU8sS0FBSyxFQUFFLEtBQUssSUFBSSxlQUFlLENBQUE7SUFDeEMsQ0FBQztDQUNGO0FBRUQsS0FBSyxVQUFVLGFBQWEsQ0FBQyxLQUFhLEVBQUUsR0FBVztJQUNyRCxJQUFJLENBQUM7UUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLFNBQVMsQ0FBQyxHQUEyQixDQUFDLENBQUE7UUFDM0QsaUZBQWlGO1FBQ2pGLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxNQUFNLFlBQVksQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtRQUVoRixPQUFPLE1BQTJCLENBQUE7SUFDcEMsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8saUJBQWlCLENBQUE7SUFDMUIsQ0FBQztBQUNILENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQVMsS0FBSyxDQUFDLEtBQWE7SUFDMUIsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQTtJQUU5QixJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssS0FBSyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFO1FBQUUsT0FBTyxpQkFBaUIsQ0FBQTtJQUV2RSxNQUFNLENBQUMsTUFBTSxFQUFFLEFBQUQsRUFBRyxFQUFFLEVBQUUsVUFBVSxFQUFFLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQTtJQUU3QyxJQUFJLFFBQWlDLENBQUE7SUFFckMsSUFBSSxDQUFDO1FBQ0gsUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUE7SUFDM0UsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8saUJBQWlCLENBQUE7SUFDMUIsQ0FBQztJQUVELElBQ0UsUUFBUSxLQUFLLElBQUk7UUFDakIsT0FBTyxRQUFRLEtBQUssUUFBUTtRQUM1QixRQUFRLENBQUMsR0FBRyxLQUFLLEtBQUs7UUFDdEIsUUFBUSxDQUFDLEdBQUcsS0FBSyxTQUFTO1FBQzFCLFFBQVEsQ0FBQyxHQUFHLEtBQUssS0FBSztRQUN0QixPQUFPLFFBQVEsQ0FBQyxHQUFHLEtBQUssUUFBUTtRQUNoQyxRQUFRLENBQUMsSUFBSSxLQUFLLFNBQVM7UUFDM0IsUUFBUSxDQUFDLEdBQUcsS0FBSyxTQUFTO1FBRTFCLE9BQU8saUJBQWlCLENBQUE7SUFFMUIsT0FBTztRQUNMLEdBQUcsRUFBRSxRQUFRLENBQUMsR0FBRztRQUNqQix1RUFBdUU7UUFDdkUsR0FBRyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQztRQUNqQyxFQUFFLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsV0FBVyxDQUFDO1FBQ2hDLFVBQVUsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxXQUFXLENBQUM7UUFDaEQsR0FBRyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLFdBQVcsQ0FBQztLQUNuQyxDQUFBO0FBQ0gsQ0FBQztBQUVELDhFQUE4RTtBQUM5RSxTQUFTLElBQUksQ0FBQyxHQUFRLEVBQUUsR0FBVztJQUNqQyxJQUFJLEdBQUcsQ0FBQyxFQUFFLENBQUMsTUFBTSxLQUFLLEVBQUUsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sS0FBSyxHQUFHO1FBQUUsT0FBTyxpQkFBaUIsQ0FBQTtJQUU1RSxJQUFJLE9BQWtCLENBQUE7SUFFdEIsSUFBSSxDQUFDO1FBQ0gsTUFBTSxRQUFRLEdBQUcsZ0JBQWdCLENBQUMsYUFBYSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUE7UUFFckUsUUFBUSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDeEIsUUFBUSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7UUFFNUIsT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQ2xCLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsRUFBRSxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FDckYsQ0FBQTtJQUNILENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxPQUFPLGlCQUFpQixDQUFBO0lBQzFCLENBQUM7SUFFRCxJQUNFLE9BQU8sS0FBSyxJQUFJO1FBQ2hCLE9BQU8sT0FBTyxLQUFLLFFBQVE7UUFDM0IsT0FBTyxPQUFPLENBQUMsR0FBRyxLQUFLLFFBQVE7UUFDL0IsT0FBTyxPQUFPLENBQUMsR0FBRyxLQUFLLFFBQVE7UUFDL0IsT0FBTyxPQUFPLENBQUMsUUFBUSxLQUFLLFFBQVE7UUFDcEMsT0FBTyxDQUFDLFFBQVEsS0FBSyxJQUFJO1FBRXpCLE9BQU8saUJBQWlCLENBQUE7SUFFMUIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFBO0lBRXRCLElBQUksT0FBTyxDQUFDLEdBQUcsS0FBSyxTQUFTLElBQUksT0FBTyxDQUFDLEdBQUcsR0FBRyxJQUFJLElBQUksR0FBRztRQUFFLE9BQU8saUJBQWlCLENBQUE7SUFFcEYsSUFBSSxPQUFPLENBQUMsR0FBRyxLQUFLLFNBQVMsSUFBSSxPQUFPLENBQUMsR0FBRyxHQUFHLElBQUksR0FBRyxHQUFHO1FBQUUsT0FBTyxpQkFBaUIsQ0FBQTtJQUVuRixPQUFPO1FBQ0wsR0FBRyxFQUFFLE9BQU8sQ0FBQyxHQUFHO1FBQ2hCLEdBQUcsRUFBRSxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLFdBQVcsRUFBRTtRQUMvQyxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsS0FBSyxTQUFTO1lBQzNCLENBQUMsQ0FBQyxFQUFFO1lBQ0osQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQztRQUN4RCxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVE7UUFDMUIsR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztLQUMzRCxDQUFBO0FBQ0gsQ0FBQztBQVVELE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQTtBQUNmLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQTtBQUNiLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQTtBQUVkLE1BQU0sU0FBUyxHQUFHLGdCQUFnQixFQUFFLENBQUMsR0FBRyxDQUFBO0FBQ3hDLE1BQU0sWUFBWSxHQUFHLGNBQWMsRUFBRSxDQUFDLEdBQUcsQ0FBQTtBQVl6QyxNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxNQUFNLGlCQUFrQixTQUFRLEtBQUs7SUFDbEQsSUFBSSxHQUFHLGVBQWUsQ0FBQTtDQUN2QyxDQUFDLEVBQUUsQ0FBQTtBQUVKLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxNQUFNLGVBQWdCLFNBQVEsS0FBSztJQUM5QyxJQUFJLEdBQUcsYUFBYSxDQUFBO0NBQ3JDLENBQUMsRUFBRSxDQUFBO0FBRUosTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLE1BQU0sY0FBZSxTQUFRLEtBQUs7SUFDNUMsSUFBSSxHQUFHLFlBQVksQ0FBQTtDQUNwQyxDQUFDLEVBQUUsQ0FBQTtBQUVKLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxNQUFNLGVBQWdCLFNBQVEsS0FBSztJQUM5QyxJQUFJLEdBQUcsYUFBYSxDQUFBO0NBQ3JDLENBQUMsRUFBRSxDQUFBIn0=
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/** @type {Promise<typeof import('jose')> | undefined} */
|
|
2
|
+
let loading;
|
|
3
|
+
// resolved once: an import per call resolves the module again on every token
|
|
4
|
+
export const load = () => (loading ??= import('jose'));
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiam9zZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NvdXJjZS9saWIvam9zZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx5REFBeUQ7QUFDekQsSUFBSSxPQUFPLENBQUE7QUFFWCw2RUFBNkU7QUFDN0UsTUFBTSxDQUFDLE1BQU0sSUFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDLENBQUMsT0FBTyxLQUFLLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFBIn0=
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { createDecipheriv } from 'node:crypto'
|
|
1
2
|
import { DecryptFactory, ImportKeyFactory } from 'paseto/v3/local'
|
|
2
3
|
import { LRUCache } from 'lru-cache'
|
|
3
4
|
import { form, jweKey } from './lib/index.ts'
|
|
4
|
-
import { load } from './lib/jose.js'
|
|
5
5
|
import type { Maybe } from '@toa.io/core/types'
|
|
6
6
|
import type { Operation } from '@toa.io/bridges.node'
|
|
7
7
|
import type { Context, Claims, DecryptOutput, JWEClaims } from './lib/index.ts'
|
|
@@ -33,37 +33,40 @@ export class Computation implements Operation {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
public async execute(token: string): Promise<Maybe<DecryptOutput>> {
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
if (form(token) === 'paseto') {
|
|
37
|
+
const kid = this.pasetoKid(token)
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
if (kid instanceof Error) return kid
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
const key = await this.key(kid, true)
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
if (key instanceof Error) return key
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
? await decryptPaseto(token, key.key)
|
|
47
|
-
: await decryptJWE(token, key.key)
|
|
45
|
+
const claims = await decryptPaseto(token, key.key)
|
|
48
46
|
|
|
49
|
-
|
|
47
|
+
if (claims instanceof Error) return claims
|
|
50
48
|
|
|
51
|
-
|
|
49
|
+
// a token of the form this component leaves behind is answered with a re-issue
|
|
50
|
+
return this.answer(claims, key, true)
|
|
51
|
+
}
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
return ERR_FORGED_KEY
|
|
53
|
+
const jwe = parse(token)
|
|
55
54
|
|
|
56
|
-
if (
|
|
55
|
+
if (jwe instanceof Error) return jwe
|
|
57
56
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
57
|
+
const key = await this.key(jwe.kid, false)
|
|
58
|
+
|
|
59
|
+
if (key instanceof Error) return key
|
|
60
|
+
|
|
61
|
+
const claims = open(jwe, key.key)
|
|
62
|
+
|
|
63
|
+
if (claims instanceof Error) return claims
|
|
64
|
+
|
|
65
|
+
return this.answer(
|
|
66
|
+
claims,
|
|
67
|
+
key,
|
|
68
|
+
jwe.kid !== this.latest && key.identity === undefined
|
|
69
|
+
)
|
|
67
70
|
}
|
|
68
71
|
|
|
69
72
|
private pasetoKid(token: string): Maybe<string> {
|
|
@@ -83,22 +86,23 @@ export class Computation implements Operation {
|
|
|
83
86
|
}
|
|
84
87
|
}
|
|
85
88
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
89
|
+
/** What both forms answer once their claims are open. */
|
|
90
|
+
private answer(claims: Claims, key: Key, refresh: boolean): Maybe<DecryptOutput> {
|
|
91
|
+
this.logs.debug('Token claims', claims)
|
|
92
|
+
|
|
93
|
+
if (key.identity !== undefined && claims.identity.id !== key.identity)
|
|
94
|
+
return ERR_FORGED_KEY
|
|
95
|
+
|
|
96
|
+
if (key.revokedAt !== undefined) return ERR_REVOKED_KEY
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
iss: claims.iss,
|
|
100
|
+
iat: claims.iat,
|
|
101
|
+
exp: claims.exp,
|
|
102
|
+
identity: claims.identity,
|
|
103
|
+
...(claims.aud === undefined ? {} : { aud: claims.aud }),
|
|
104
|
+
refresh,
|
|
105
|
+
custom: key.identity !== undefined
|
|
102
106
|
}
|
|
103
107
|
}
|
|
104
108
|
|
|
@@ -131,40 +135,107 @@ async function decryptPaseto(token: string, key: string): Promise<Maybe<Claims>>
|
|
|
131
135
|
}
|
|
132
136
|
}
|
|
133
137
|
|
|
134
|
-
|
|
138
|
+
/**
|
|
139
|
+
* The five parts of a compact JWE (RFC 7516), of the one form this component issues: `dir`, so
|
|
140
|
+
* the encrypted key is empty, `A256GCM`, and a `kid` naming the key. A header that asks for
|
|
141
|
+
* anything else — another algorithm, a critical extension, compression — is refused, as jose
|
|
142
|
+
* refuses it.
|
|
143
|
+
*/
|
|
144
|
+
function parse(token: string): Maybe<JWE> {
|
|
145
|
+
const parts = token.split('.')
|
|
146
|
+
|
|
147
|
+
if (parts.length !== PARTS || parts[1] !== '') return ERR_INVALID_TOKEN
|
|
148
|
+
|
|
149
|
+
const [header, , iv, ciphertext, tag] = parts
|
|
150
|
+
|
|
151
|
+
let declared: Record<string, unknown>
|
|
152
|
+
|
|
135
153
|
try {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
contentEncryptionAlgorithms: ['A256GCM']
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
if (
|
|
144
|
-
typeof payload.iss !== 'string' ||
|
|
145
|
-
typeof payload.iat !== 'number' ||
|
|
146
|
-
typeof payload.identity !== 'object' ||
|
|
147
|
-
payload.identity === null
|
|
148
|
-
)
|
|
149
|
-
return ERR_INVALID_TOKEN
|
|
154
|
+
declared = JSON.parse(Buffer.from(header, 'base64url').toString('utf-8'))
|
|
155
|
+
} catch {
|
|
156
|
+
return ERR_INVALID_TOKEN
|
|
157
|
+
}
|
|
150
158
|
|
|
151
|
-
|
|
152
|
-
|
|
159
|
+
if (
|
|
160
|
+
declared === null ||
|
|
161
|
+
typeof declared !== 'object' ||
|
|
162
|
+
declared.alg !== 'dir' ||
|
|
163
|
+
declared.enc !== 'A256GCM' ||
|
|
164
|
+
declared.typ !== 'JWT' ||
|
|
165
|
+
typeof declared.kid !== 'string' ||
|
|
166
|
+
declared.crit !== undefined ||
|
|
167
|
+
declared.zip !== undefined
|
|
168
|
+
)
|
|
169
|
+
return ERR_INVALID_TOKEN
|
|
153
170
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
171
|
+
return {
|
|
172
|
+
kid: declared.kid,
|
|
173
|
+
// the header as it was written, which is what it was encrypted against
|
|
174
|
+
aad: Buffer.from(header, 'ascii'),
|
|
175
|
+
iv: Buffer.from(iv, 'base64url'),
|
|
176
|
+
ciphertext: Buffer.from(ciphertext, 'base64url'),
|
|
177
|
+
tag: Buffer.from(tag, 'base64url')
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** The claims a token carries, where its tag holds and its times admit it. */
|
|
182
|
+
function open(jwe: JWE, key: string): Maybe<Claims> {
|
|
183
|
+
if (jwe.iv.length !== IV || jwe.tag.length !== TAG) return ERR_INVALID_TOKEN
|
|
184
|
+
|
|
185
|
+
let payload: JWEClaims
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
const decipher = createDecipheriv('aes-256-gcm', jweKey(key), jwe.iv)
|
|
189
|
+
|
|
190
|
+
decipher.setAAD(jwe.aad)
|
|
191
|
+
decipher.setAuthTag(jwe.tag)
|
|
192
|
+
|
|
193
|
+
payload = JSON.parse(
|
|
194
|
+
Buffer.concat([decipher.update(jwe.ciphertext), decipher.final()]).toString('utf-8')
|
|
195
|
+
)
|
|
163
196
|
} catch {
|
|
164
197
|
return ERR_INVALID_TOKEN
|
|
165
198
|
}
|
|
199
|
+
|
|
200
|
+
if (
|
|
201
|
+
payload === null ||
|
|
202
|
+
typeof payload !== 'object' ||
|
|
203
|
+
typeof payload.iss !== 'string' ||
|
|
204
|
+
typeof payload.iat !== 'number' ||
|
|
205
|
+
typeof payload.identity !== 'object' ||
|
|
206
|
+
payload.identity === null
|
|
207
|
+
)
|
|
208
|
+
return ERR_INVALID_TOKEN
|
|
209
|
+
|
|
210
|
+
const now = Date.now()
|
|
211
|
+
|
|
212
|
+
if (payload.exp !== undefined && payload.exp * 1000 <= now) return ERR_INVALID_TOKEN
|
|
213
|
+
|
|
214
|
+
if (payload.nbf !== undefined && payload.nbf * 1000 > now) return ERR_INVALID_TOKEN
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
iss: payload.iss,
|
|
218
|
+
iat: new Date(payload.iat * 1000).toISOString(),
|
|
219
|
+
...(payload.exp === undefined
|
|
220
|
+
? {}
|
|
221
|
+
: { exp: new Date(payload.exp * 1000).toISOString() }),
|
|
222
|
+
identity: payload.identity,
|
|
223
|
+
...(payload.aud === undefined ? {} : { aud: payload.aud })
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
interface JWE {
|
|
228
|
+
kid: string
|
|
229
|
+
aad: Buffer
|
|
230
|
+
iv: Buffer
|
|
231
|
+
ciphertext: Buffer
|
|
232
|
+
tag: Buffer
|
|
166
233
|
}
|
|
167
234
|
|
|
235
|
+
const PARTS = 5
|
|
236
|
+
const IV = 12
|
|
237
|
+
const TAG = 16
|
|
238
|
+
|
|
168
239
|
const importKey = ImportKeyFactory().run
|
|
169
240
|
const decryptLocal = DecryptFactory().run
|
|
170
241
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type { Options, Query, RemoteError } from '@toa.io/core/types'
|
|
5
5
|
import type { Secret } from '@toa.io/extensions.configuration'
|
|
6
6
|
import type { FetchInit } from '@toa.io/extensions.fetch'
|
|
7
|
-
import type { Logs, Span } from '@toa.io/extensions.telemetry'
|
|
7
|
+
import type { Logs, Metrics, Span } from '@toa.io/extensions.telemetry'
|
|
8
8
|
import type { Readable } from 'node:stream'
|
|
9
9
|
|
|
10
10
|
export interface Entity {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/extensions.exposition",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.304",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Toa Exposition",
|
|
6
6
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
@@ -28,16 +28,16 @@
|
|
|
28
28
|
"!**/.env*"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@toa.io/core": "1.0.0-alpha.
|
|
32
|
-
"@toa.io/definitions": "1.0.0-alpha.
|
|
33
|
-
"@toa.io/generic": "1.0.0-alpha.
|
|
34
|
-
"@toa.io/schemas": "1.0.0-alpha.
|
|
31
|
+
"@toa.io/core": "1.0.0-alpha.304",
|
|
32
|
+
"@toa.io/definitions": "1.0.0-alpha.304",
|
|
33
|
+
"@toa.io/generic": "1.0.0-alpha.304",
|
|
34
|
+
"@toa.io/schemas": "1.0.0-alpha.304",
|
|
35
35
|
"content-type": "3.0.0",
|
|
36
36
|
"matchacho": "0.6.1",
|
|
37
37
|
"minimatch": "10.2.6",
|
|
38
38
|
"msgpackr": "2.1.0",
|
|
39
39
|
"negotiator": "1.1.0",
|
|
40
|
-
"openspan": "1.0.0-alpha.
|
|
40
|
+
"openspan": "1.0.0-alpha.304"
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
43
|
"test": "echo \"Error: run tests from root\" && exit 1",
|
|
@@ -72,5 +72,5 @@
|
|
|
72
72
|
"lru-cache": "11.5.2",
|
|
73
73
|
"paseto": "4.0.1"
|
|
74
74
|
},
|
|
75
|
-
"gitHead": "
|
|
75
|
+
"gitHead": "a95a5a5a64922b11b23142d4acbcee1331ed31aa"
|
|
76
76
|
}
|