@shipfox/api-auth 18.0.0 → 20.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +17 -2
- package/CHANGELOG.md +47 -0
- package/README.md +24 -9
- package/dist/core/administration.d.ts +15 -0
- package/dist/core/administration.d.ts.map +1 -1
- package/dist/core/administration.js +44 -2
- package/dist/core/administration.js.map +1 -1
- package/dist/core/auth.d.ts.map +1 -1
- package/dist/core/auth.js +5 -3
- package/dist/core/auth.js.map +1 -1
- package/dist/core/cimd.d.ts +39 -0
- package/dist/core/cimd.d.ts.map +1 -0
- package/dist/core/cimd.js +392 -0
- package/dist/core/cimd.js.map +1 -0
- package/dist/core/entities/agent-access.d.ts +75 -0
- package/dist/core/entities/agent-access.d.ts.map +1 -0
- package/dist/core/entities/agent-access.js +3 -0
- package/dist/core/entities/agent-access.js.map +1 -0
- package/dist/core/errors.d.ts +17 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +32 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/oauth-client-resolver.d.ts +54 -0
- package/dist/core/oauth-client-resolver.d.ts.map +1 -0
- package/dist/core/oauth-client-resolver.js +154 -0
- package/dist/core/oauth-client-resolver.js.map +1 -0
- package/dist/core/oauth-client.d.ts +39 -0
- package/dist/core/oauth-client.d.ts.map +1 -0
- package/dist/core/oauth-client.js +236 -0
- package/dist/core/oauth-client.js.map +1 -0
- package/dist/db/admin-user-moderation.d.ts.map +1 -1
- package/dist/db/admin-user-moderation.js +30 -26
- package/dist/db/admin-user-moderation.js.map +1 -1
- package/dist/db/admin-user-summary.d.ts +22 -0
- package/dist/db/admin-user-summary.d.ts.map +1 -1
- package/dist/db/admin-user-summary.js +75 -1
- package/dist/db/admin-user-summary.js.map +1 -1
- package/dist/db/admin-users.d.ts +11 -0
- package/dist/db/admin-users.d.ts.map +1 -1
- package/dist/db/admin-users.js +4 -1
- package/dist/db/admin-users.js.map +1 -1
- package/dist/db/agent-access-retention.d.ts +10 -0
- package/dist/db/agent-access-retention.d.ts.map +1 -0
- package/dist/db/agent-access-retention.js +11 -0
- package/dist/db/agent-access-retention.js.map +1 -0
- package/dist/db/agent-access.d.ts +255 -0
- package/dist/db/agent-access.d.ts.map +1 -0
- package/dist/db/agent-access.js +705 -0
- package/dist/db/agent-access.js.map +1 -0
- package/dist/db/db.d.ts +2604 -238
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/db.js +7 -0
- package/dist/db/db.js.map +1 -1
- package/dist/db/schema/agent-access.d.ts +1204 -0
- package/dist/db/schema/agent-access.d.ts.map +1 -0
- package/dist/db/schema/agent-access.js +267 -0
- package/dist/db/schema/agent-access.js.map +1 -0
- package/dist/db/schema/users.d.ts.map +1 -1
- package/dist/db/schema/users.js +8 -3
- package/dist/db/schema/users.js.map +1 -1
- package/dist/index.d.ts +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -2
- package/dist/index.js.map +1 -1
- package/dist/metrics/instance.d.ts +1 -1
- package/dist/metrics/instance.d.ts.map +1 -1
- package/dist/metrics/instance.js.map +1 -1
- package/dist/presentation/routes/administration.d.ts.map +1 -1
- package/dist/presentation/routes/administration.js +123 -20
- package/dist/presentation/routes/administration.js.map +1 -1
- package/dist/presentation/routes/email-verification/verify-email-resend.d.ts.map +1 -1
- package/dist/presentation/routes/email-verification/verify-email-resend.js +6 -1
- package/dist/presentation/routes/email-verification/verify-email-resend.js.map +1 -1
- package/dist/presentation/routes/oauth.d.ts +9 -0
- package/dist/presentation/routes/oauth.d.ts.map +1 -0
- package/dist/presentation/routes/oauth.js +150 -0
- package/dist/presentation/routes/oauth.js.map +1 -0
- package/dist/presentation/routes/rate-limit.d.ts.map +1 -1
- package/dist/presentation/routes/rate-limit.js +34 -0
- package/dist/presentation/routes/rate-limit.js.map +1 -1
- package/dist/presentation/routes/registration/signup.d.ts.map +1 -1
- package/dist/presentation/routes/registration/signup.js +59 -50
- package/dist/presentation/routes/registration/signup.js.map +1 -1
- package/dist/temporal/activities/agent-access-retention.d.ts +13 -0
- package/dist/temporal/activities/agent-access-retention.d.ts.map +1 -0
- package/dist/temporal/activities/agent-access-retention.js +58 -0
- package/dist/temporal/activities/agent-access-retention.js.map +1 -0
- package/dist/temporal/activities/index.d.ts +5 -0
- package/dist/temporal/activities/index.d.ts.map +1 -0
- package/dist/temporal/activities/index.js +8 -0
- package/dist/temporal/activities/index.js.map +1 -0
- package/dist/temporal/constants.d.ts +2 -0
- package/dist/temporal/constants.d.ts.map +1 -0
- package/dist/temporal/constants.js +3 -0
- package/dist/temporal/constants.js.map +1 -0
- package/dist/temporal/workflows/agent-access-retention-cron.d.ts +2 -0
- package/dist/temporal/workflows/agent-access-retention-cron.d.ts.map +1 -0
- package/dist/temporal/workflows/agent-access-retention-cron.js +22 -0
- package/dist/temporal/workflows/agent-access-retention-cron.js.map +1 -0
- package/dist/temporal/workflows/index.bundle.js +25227 -0
- package/dist/temporal/workflows/index.bundle.meta.json +1 -0
- package/dist/temporal/workflows/index.d.ts +2 -0
- package/dist/temporal/workflows/index.d.ts.map +1 -0
- package/dist/temporal/workflows/index.js +3 -0
- package/dist/temporal/workflows/index.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/drizzle/0003_brainy_luckman.sql +6 -0
- package/drizzle/0004_yummy_runaways.sql +110 -0
- package/drizzle/meta/0003_snapshot.json +844 -0
- package/drizzle/meta/0004_snapshot.json +1751 -0
- package/drizzle/meta/_journal.json +14 -0
- package/package.json +11 -8
- package/src/core/admin-role.test.ts +70 -0
- package/src/core/administration.ts +78 -1
- package/src/core/auth.ts +3 -5
- package/src/core/cimd.test.ts +213 -0
- package/src/core/cimd.ts +532 -0
- package/src/core/entities/agent-access.ts +80 -0
- package/src/core/errors.ts +48 -0
- package/src/core/oauth-client-resolver.test.ts +198 -0
- package/src/core/oauth-client-resolver.ts +253 -0
- package/src/core/oauth-client.test.ts +157 -0
- package/src/core/oauth-client.ts +331 -0
- package/src/db/admin-user-moderation.ts +53 -45
- package/src/db/admin-user-summary.test.ts +228 -0
- package/src/db/admin-user-summary.ts +143 -1
- package/src/db/admin-users.ts +21 -1
- package/src/db/agent-access-retention.ts +10 -0
- package/src/db/agent-access.test.ts +1064 -0
- package/src/db/agent-access.ts +1491 -0
- package/src/db/db.ts +14 -0
- package/src/db/schema/agent-access.ts +273 -0
- package/src/db/schema/users.ts +9 -3
- package/src/index.test.ts +27 -0
- package/src/index.ts +82 -0
- package/src/metrics/instance.ts +6 -1
- package/src/presentation/routes/administration.test.ts +359 -2
- package/src/presentation/routes/administration.ts +142 -20
- package/src/presentation/routes/email-verification/verify-email-resend.ts +7 -1
- package/src/presentation/routes/oauth.test.ts +133 -0
- package/src/presentation/routes/oauth.ts +144 -0
- package/src/presentation/routes/rate-limit.ts +16 -0
- package/src/presentation/routes/registration/signup.ts +52 -41
- package/src/temporal/activities/agent-access-retention.ts +76 -0
- package/src/temporal/activities/index.ts +5 -0
- package/src/temporal/constants.ts +1 -0
- package/src/temporal/workflows/agent-access-retention-cron.ts +23 -0
- package/src/temporal/workflows/index.ts +1 -0
- package/test/globalSetup.ts +1 -1
- package/test/routes.ts +3 -1
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { promises as dnsPromises } from 'node:dns';
|
|
2
|
+
import { request as httpsRequest } from 'node:https';
|
|
3
|
+
import { isIP } from 'node:net';
|
|
4
|
+
import { oauthClientMetadataDocumentSchema } from '@shipfox/api-auth-dto';
|
|
5
|
+
import { InvalidOAuthClientMetadataError, OAuthMetadataFetchError } from './errors.js';
|
|
6
|
+
import { OAUTH_CIMD_CACHE_MAX_AGE_SECONDS, validateOAuthClientId, validateOAuthClientMetadataDocument } from './oauth-client.js';
|
|
7
|
+
export const OAUTH_CIMD_MAX_BODY_BYTES = 256 * 1024;
|
|
8
|
+
export const OAUTH_CIMD_FETCH_TIMEOUT_MS = 5_000;
|
|
9
|
+
const DECIMAL_RE = /^\d+$/u;
|
|
10
|
+
const IPV6_GROUP_RE = /^[0-9a-f]{1,4}$/u;
|
|
11
|
+
let CimdTimeoutError = class CimdTimeoutError extends Error {
|
|
12
|
+
constructor(){
|
|
13
|
+
super('CIMD fetch timed out');
|
|
14
|
+
this.name = 'CimdTimeoutError';
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
function metadataFetchError(reason, cause) {
|
|
18
|
+
return new OAuthMetadataFetchError(reason, cause);
|
|
19
|
+
}
|
|
20
|
+
function ipv4ToNumber(value) {
|
|
21
|
+
const parts = value.split('.');
|
|
22
|
+
if (parts.length !== 4) return undefined;
|
|
23
|
+
let result = 0;
|
|
24
|
+
for (const part of parts){
|
|
25
|
+
if (!DECIMAL_RE.test(part)) return undefined;
|
|
26
|
+
const octet = Number(part);
|
|
27
|
+
if (!Number.isInteger(octet) || octet > 255) return undefined;
|
|
28
|
+
result = result * 256 + octet;
|
|
29
|
+
}
|
|
30
|
+
return result >>> 0;
|
|
31
|
+
}
|
|
32
|
+
function inIpv4Range(value, start, end) {
|
|
33
|
+
return value >= start && value <= end;
|
|
34
|
+
}
|
|
35
|
+
function isPublicIpv4(value) {
|
|
36
|
+
const address = ipv4ToNumber(value);
|
|
37
|
+
if (address === undefined) return false;
|
|
38
|
+
return !(inIpv4Range(address, 0x00000000, 0x00ffffff) || // 0.0.0.0/8
|
|
39
|
+
inIpv4Range(address, 0x0a000000, 0x0affffff) || // 10.0.0.0/8
|
|
40
|
+
inIpv4Range(address, 0x64400000, 0x647fffff) || // 100.64.0.0/10
|
|
41
|
+
inIpv4Range(address, 0x7f000000, 0x7fffffff) || // 127.0.0.0/8
|
|
42
|
+
inIpv4Range(address, 0xa9fe0000, 0xa9feffff) || // 169.254.0.0/16
|
|
43
|
+
inIpv4Range(address, 0xac100000, 0xac1fffff) || // 172.16.0.0/12
|
|
44
|
+
inIpv4Range(address, 0xc0000000, 0xc00000ff) || // 192.0.0.0/24
|
|
45
|
+
inIpv4Range(address, 0xc0000200, 0xc00002ff) || // 192.0.2.0/24
|
|
46
|
+
inIpv4Range(address, 0xc01fc400, 0xc01fc4ff) || // 192.31.196.0/24
|
|
47
|
+
inIpv4Range(address, 0xc034c100, 0xc034c1ff) || // 192.52.193.0/24
|
|
48
|
+
inIpv4Range(address, 0xc0586300, 0xc05863ff) || // 192.88.99.0/24
|
|
49
|
+
inIpv4Range(address, 0xc0a80000, 0xc0a8ffff) || // 192.168.0.0/16
|
|
50
|
+
inIpv4Range(address, 0xc0af3000, 0xc0af30ff) || // 192.175.48.0/24
|
|
51
|
+
inIpv4Range(address, 0xc6120000, 0xc613ffff) || // 198.18.0.0/15
|
|
52
|
+
inIpv4Range(address, 0xc6336400, 0xc63364ff) || // 198.51.100.0/24
|
|
53
|
+
inIpv4Range(address, 0xcb007100, 0xcb0071ff) || // 203.0.113.0/24
|
|
54
|
+
inIpv4Range(address, 0xe0000000, 0xffffffff) // multicast, reserved, broadcast
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
function parseIpv6(value) {
|
|
58
|
+
if (value.includes('%')) return undefined;
|
|
59
|
+
const input = expandEmbeddedIpv4(value.toLowerCase());
|
|
60
|
+
if (input === undefined) return undefined;
|
|
61
|
+
const parts = splitIpv6Groups(input);
|
|
62
|
+
if (parts === undefined) return undefined;
|
|
63
|
+
const { left, right, hasCompression } = parts;
|
|
64
|
+
const groups = hasCompression ? [
|
|
65
|
+
...left,
|
|
66
|
+
...Array(8 - left.length - right.length).fill('0'),
|
|
67
|
+
...right
|
|
68
|
+
] : [
|
|
69
|
+
...left,
|
|
70
|
+
...right
|
|
71
|
+
];
|
|
72
|
+
if (groups.length !== 8) return undefined;
|
|
73
|
+
return groups.map((part)=>BigInt(`0x${part}`));
|
|
74
|
+
}
|
|
75
|
+
function expandEmbeddedIpv4(value) {
|
|
76
|
+
if (!value.includes('.')) return value;
|
|
77
|
+
const lastColon = value.lastIndexOf(':');
|
|
78
|
+
if (lastColon < 0) return undefined;
|
|
79
|
+
const ipv4 = ipv4ToNumber(value.slice(lastColon + 1));
|
|
80
|
+
if (ipv4 === undefined) return undefined;
|
|
81
|
+
const high = (ipv4 >>> 16 & 0xffff).toString(16);
|
|
82
|
+
const low = (ipv4 & 0xffff).toString(16);
|
|
83
|
+
return `${value.slice(0, lastColon)}:${high}:${low}`;
|
|
84
|
+
}
|
|
85
|
+
function splitIpv6Groups(value) {
|
|
86
|
+
const compressionStart = value.indexOf('::');
|
|
87
|
+
if (compressionStart !== -1 && compressionStart !== value.lastIndexOf('::')) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
const hasCompression = compressionStart !== -1;
|
|
91
|
+
const [leftText, rightText = ''] = value.split('::');
|
|
92
|
+
const left = leftText ? leftText.split(':') : [];
|
|
93
|
+
const right = rightText ? rightText.split(':') : [];
|
|
94
|
+
if (left.some((part)=>!IPV6_GROUP_RE.test(part))) return undefined;
|
|
95
|
+
if (right.some((part)=>!IPV6_GROUP_RE.test(part))) return undefined;
|
|
96
|
+
if (!hasCompression && left.length + right.length !== 8) return undefined;
|
|
97
|
+
if (hasCompression && left.length + right.length >= 8) return undefined;
|
|
98
|
+
return {
|
|
99
|
+
hasCompression,
|
|
100
|
+
left,
|
|
101
|
+
right
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function isPublicIpv6(value) {
|
|
105
|
+
const groups = parseIpv6(value);
|
|
106
|
+
if (!groups) return false;
|
|
107
|
+
const first = Number(groups[0]);
|
|
108
|
+
if (first < 0x2000 || first > 0x3fff) return false;
|
|
109
|
+
// Keep documentation, benchmarking, transition, and other special-use
|
|
110
|
+
// prefixes out of a fetch path even when a resolver returns a routable one.
|
|
111
|
+
if (first === 0x2001) {
|
|
112
|
+
const second = Number(groups[1]);
|
|
113
|
+
if (second === 0x0000 || second === 0x0002 || second >= 0x0010 && second <= 0x002f || second >= 0x0db8 && second <= 0x0dbf) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (first === 0x2002 || first === 0x3fff) return false;
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
/** Returns true only for a globally routable unicast address. */ export function isPublicUnicastAddress(address, family) {
|
|
121
|
+
const normalized = address.replace(/^\[|\]$/gu, '');
|
|
122
|
+
const detectedFamily = family ?? isIP(normalized);
|
|
123
|
+
if (detectedFamily === 4) return isPublicIpv4(normalized);
|
|
124
|
+
if (detectedFamily === 6) return isPublicIpv6(normalized);
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
function normalizeHostname(url) {
|
|
128
|
+
return url.hostname.replace(/^\[|\]$/gu, '');
|
|
129
|
+
}
|
|
130
|
+
async function resolvePublicAddress(hostname) {
|
|
131
|
+
if (isIP(hostname) === 4 || isIP(hostname) === 6) {
|
|
132
|
+
const family = isIP(hostname);
|
|
133
|
+
if (!isPublicUnicastAddress(hostname, family)) {
|
|
134
|
+
throw metadataFetchError('private-address');
|
|
135
|
+
}
|
|
136
|
+
return [
|
|
137
|
+
{
|
|
138
|
+
address: hostname,
|
|
139
|
+
family
|
|
140
|
+
}
|
|
141
|
+
];
|
|
142
|
+
}
|
|
143
|
+
let resolved;
|
|
144
|
+
try {
|
|
145
|
+
resolved = await dnsPromises.lookup(hostname, {
|
|
146
|
+
all: true,
|
|
147
|
+
verbatim: true
|
|
148
|
+
});
|
|
149
|
+
} catch (error) {
|
|
150
|
+
throw metadataFetchError('dns-failed', error);
|
|
151
|
+
}
|
|
152
|
+
if (resolved.length === 0) throw metadataFetchError('dns-failed');
|
|
153
|
+
const addresses = resolved.map((entry)=>({
|
|
154
|
+
address: entry.address,
|
|
155
|
+
family: entry.family
|
|
156
|
+
}));
|
|
157
|
+
if (addresses.some((entry)=>entry.family !== 4 && entry.family !== 6 || !isPublicUnicastAddress(entry.address, entry.family))) {
|
|
158
|
+
throw metadataFetchError('private-address');
|
|
159
|
+
}
|
|
160
|
+
return addresses;
|
|
161
|
+
}
|
|
162
|
+
function headerValue(headers, name) {
|
|
163
|
+
const normalizedName = name.toLowerCase();
|
|
164
|
+
const headerName = Object.keys(headers).find((key)=>key.toLowerCase() === normalizedName);
|
|
165
|
+
const value = headerName === undefined ? undefined : headers[headerName];
|
|
166
|
+
if (Array.isArray(value)) return value.join(', ');
|
|
167
|
+
return value;
|
|
168
|
+
}
|
|
169
|
+
function parseCacheMaxAge(headers) {
|
|
170
|
+
const cacheControl = headerValue(headers, 'cache-control');
|
|
171
|
+
if (!cacheControl) return OAUTH_CIMD_CACHE_MAX_AGE_SECONDS;
|
|
172
|
+
let maxAge;
|
|
173
|
+
for (const directive of cacheControl.split(',')){
|
|
174
|
+
const [rawName, rawValue] = directive.trim().split('=', 2);
|
|
175
|
+
const name = rawName?.trim().toLowerCase();
|
|
176
|
+
if (name === 'no-store' || name === 'no-cache') return 0;
|
|
177
|
+
if (name === 'max-age' && rawValue !== undefined && DECIMAL_RE.test(rawValue.trim())) {
|
|
178
|
+
maxAge = Number(rawValue.trim());
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return Math.min(maxAge ?? OAUTH_CIMD_CACHE_MAX_AGE_SECONDS, OAUTH_CIMD_CACHE_MAX_AGE_SECONDS);
|
|
182
|
+
}
|
|
183
|
+
function withTimeout(promise, timeoutMs, onTimeout) {
|
|
184
|
+
return new Promise((resolve, reject)=>{
|
|
185
|
+
let settled = false;
|
|
186
|
+
const timer = setTimeout(()=>{
|
|
187
|
+
if (settled) return;
|
|
188
|
+
settled = true;
|
|
189
|
+
onTimeout?.();
|
|
190
|
+
reject(new CimdTimeoutError());
|
|
191
|
+
}, timeoutMs);
|
|
192
|
+
promise.then((value)=>{
|
|
193
|
+
if (settled) return;
|
|
194
|
+
settled = true;
|
|
195
|
+
clearTimeout(timer);
|
|
196
|
+
resolve(value);
|
|
197
|
+
}, (error)=>{
|
|
198
|
+
if (settled) return;
|
|
199
|
+
settled = true;
|
|
200
|
+
clearTimeout(timer);
|
|
201
|
+
reject(error);
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
function requestPinnedHttps(params) {
|
|
206
|
+
return new Promise((resolve, reject)=>{
|
|
207
|
+
const hostname = normalizeHostname(params.url);
|
|
208
|
+
let settled = false;
|
|
209
|
+
const fail = (error)=>{
|
|
210
|
+
if (settled) return;
|
|
211
|
+
settled = true;
|
|
212
|
+
reject(error);
|
|
213
|
+
};
|
|
214
|
+
const succeed = (response)=>{
|
|
215
|
+
if (settled) return;
|
|
216
|
+
settled = true;
|
|
217
|
+
resolve(response);
|
|
218
|
+
};
|
|
219
|
+
if (params.url.protocol !== 'https:' || params.url.username || params.url.password) {
|
|
220
|
+
fail(metadataFetchError('invalid-url'));
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const request = httpsRequest({
|
|
224
|
+
hostname,
|
|
225
|
+
port: params.url.port || 443,
|
|
226
|
+
path: `${params.url.pathname || '/'}${params.url.search}`,
|
|
227
|
+
method: 'GET',
|
|
228
|
+
headers: {
|
|
229
|
+
accept: 'application/json'
|
|
230
|
+
},
|
|
231
|
+
rejectUnauthorized: true,
|
|
232
|
+
servername: hostname,
|
|
233
|
+
timeout: params.timeoutMs,
|
|
234
|
+
signal: params.signal,
|
|
235
|
+
// The address was resolved before this request and is the only value
|
|
236
|
+
// the TLS connection is allowed to use.
|
|
237
|
+
lookup: (_lookupHostname, _options, callback)=>{
|
|
238
|
+
callback(null, params.address.address, params.address.family);
|
|
239
|
+
}
|
|
240
|
+
}, (response)=>{
|
|
241
|
+
handleCimdResponse(response, params.maxBodyBytes, fail, succeed);
|
|
242
|
+
});
|
|
243
|
+
request.once('error', (error)=>fail(error));
|
|
244
|
+
request.once('timeout', ()=>{
|
|
245
|
+
request.destroy();
|
|
246
|
+
fail(metadataFetchError('timeout'));
|
|
247
|
+
});
|
|
248
|
+
request.end();
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
function responseHeaderError(statusCode, headers, maxBodyBytes) {
|
|
252
|
+
if (statusCode !== undefined && statusCode >= 300 && statusCode < 400) {
|
|
253
|
+
return metadataFetchError('redirected');
|
|
254
|
+
}
|
|
255
|
+
const contentLength = headerValue(headers, 'content-length');
|
|
256
|
+
if (contentLength !== undefined) {
|
|
257
|
+
if (!DECIMAL_RE.test(contentLength.trim())) return metadataFetchError('invalid-response');
|
|
258
|
+
if (Number(contentLength) > maxBodyBytes) return metadataFetchError('response-too-large');
|
|
259
|
+
}
|
|
260
|
+
const contentEncoding = headerValue(headers, 'content-encoding');
|
|
261
|
+
if (contentEncoding && contentEncoding.toLowerCase() !== 'identity') {
|
|
262
|
+
return metadataFetchError('invalid-response');
|
|
263
|
+
}
|
|
264
|
+
return undefined;
|
|
265
|
+
}
|
|
266
|
+
function readCimdResponseBody(response, maxBodyBytes) {
|
|
267
|
+
return new Promise((resolve, reject)=>{
|
|
268
|
+
const chunks = [];
|
|
269
|
+
let size = 0;
|
|
270
|
+
response.on('data', (chunk)=>{
|
|
271
|
+
const buffer = typeof chunk === 'string' ? Buffer.from(chunk) : chunk;
|
|
272
|
+
size += buffer.byteLength;
|
|
273
|
+
if (size > maxBodyBytes) {
|
|
274
|
+
response.destroy();
|
|
275
|
+
reject(metadataFetchError('response-too-large'));
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
chunks.push(buffer);
|
|
279
|
+
});
|
|
280
|
+
response.once('error', reject);
|
|
281
|
+
response.once('end', ()=>resolve(Buffer.concat(chunks)));
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
function handleCimdResponse(response, maxBodyBytes, fail, succeed) {
|
|
285
|
+
const headers = response.headers;
|
|
286
|
+
const headerError = responseHeaderError(response.statusCode, headers, maxBodyBytes);
|
|
287
|
+
if (headerError) {
|
|
288
|
+
response.destroy();
|
|
289
|
+
fail(headerError);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
void readCimdResponseBody(response, maxBodyBytes).then((body)=>succeed({
|
|
293
|
+
statusCode: response.statusCode ?? 0,
|
|
294
|
+
headers,
|
|
295
|
+
body
|
|
296
|
+
}), fail);
|
|
297
|
+
}
|
|
298
|
+
function parseCimdDocument(body, clientId) {
|
|
299
|
+
let parsed;
|
|
300
|
+
try {
|
|
301
|
+
parsed = JSON.parse(Buffer.from(body).toString('utf8'));
|
|
302
|
+
} catch {
|
|
303
|
+
throw new InvalidOAuthClientMetadataError();
|
|
304
|
+
}
|
|
305
|
+
const result = oauthClientMetadataDocumentSchema.safeParse(parsed);
|
|
306
|
+
if (!result.success) throw new InvalidOAuthClientMetadataError();
|
|
307
|
+
return validateOAuthClientMetadataDocument(result.data, clientId);
|
|
308
|
+
}
|
|
309
|
+
async function resolvePinnedAddresses(hostname, resolveAddress, timeoutMs) {
|
|
310
|
+
let resolved;
|
|
311
|
+
try {
|
|
312
|
+
resolved = await withTimeout(resolveAddress(hostname), timeoutMs);
|
|
313
|
+
} catch (error) {
|
|
314
|
+
if (error instanceof OAuthMetadataFetchError) throw error;
|
|
315
|
+
if (error instanceof CimdTimeoutError) throw metadataFetchError('timeout', error);
|
|
316
|
+
throw metadataFetchError('dns-failed', error);
|
|
317
|
+
}
|
|
318
|
+
if (resolved.length === 0) throw metadataFetchError('dns-failed');
|
|
319
|
+
if (resolved.some((entry)=>entry.family !== 4 && entry.family !== 6 || !isPublicUnicastAddress(entry.address, entry.family))) {
|
|
320
|
+
throw metadataFetchError('private-address');
|
|
321
|
+
}
|
|
322
|
+
return resolved;
|
|
323
|
+
}
|
|
324
|
+
async function requestCimdResponse(params) {
|
|
325
|
+
const abortController = new AbortController();
|
|
326
|
+
try {
|
|
327
|
+
return await withTimeout(params.request({
|
|
328
|
+
url: params.url,
|
|
329
|
+
address: params.address,
|
|
330
|
+
timeoutMs: params.timeoutMs,
|
|
331
|
+
maxBodyBytes: params.maxBodyBytes,
|
|
332
|
+
signal: abortController.signal
|
|
333
|
+
}), params.timeoutMs, ()=>abortController.abort());
|
|
334
|
+
} catch (error) {
|
|
335
|
+
if (error instanceof OAuthMetadataFetchError) throw error;
|
|
336
|
+
if (error instanceof CimdTimeoutError) throw metadataFetchError('timeout', error);
|
|
337
|
+
throw metadataFetchError('connection-failed', error);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
function remainingTimeout(deadlineMs) {
|
|
341
|
+
const timeoutMs = deadlineMs - Date.now();
|
|
342
|
+
if (timeoutMs <= 0) throw metadataFetchError('timeout');
|
|
343
|
+
return timeoutMs;
|
|
344
|
+
}
|
|
345
|
+
function assertCimdResponse(response, maxBodyBytes) {
|
|
346
|
+
const headerError = responseHeaderError(response.statusCode, response.headers, maxBodyBytes);
|
|
347
|
+
if (headerError) throw headerError;
|
|
348
|
+
if (response.statusCode !== 200) throw metadataFetchError('invalid-response');
|
|
349
|
+
if (response.body.byteLength > maxBodyBytes) {
|
|
350
|
+
throw metadataFetchError('response-too-large');
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Fetches a Client ID Metadata Document after resolving and pinning a public
|
|
355
|
+
* address. This deliberately does not share the general egress helper: CIMD
|
|
356
|
+
* has stricter public-only, no-redirect, and no-credential requirements.
|
|
357
|
+
*/ export async function fetchClientIdMetadata(clientId, options = {}) {
|
|
358
|
+
const url = validateOAuthClientId(clientId);
|
|
359
|
+
const timeoutMs = options.timeoutMs ?? OAUTH_CIMD_FETCH_TIMEOUT_MS;
|
|
360
|
+
const maxBodyBytes = options.maxBodyBytes ?? OAUTH_CIMD_MAX_BODY_BYTES;
|
|
361
|
+
const resolveAddress = options.resolveAddress ?? resolvePublicAddress;
|
|
362
|
+
const request = options.request ?? requestPinnedHttps;
|
|
363
|
+
const hostname = normalizeHostname(url);
|
|
364
|
+
const deadlineMs = Date.now() + timeoutMs;
|
|
365
|
+
const addresses = await resolvePinnedAddresses(hostname, resolveAddress, remainingTimeout(deadlineMs));
|
|
366
|
+
let lastConnectionError;
|
|
367
|
+
for (const [index, address] of addresses.entries()){
|
|
368
|
+
try {
|
|
369
|
+
const response = await requestCimdResponse({
|
|
370
|
+
url,
|
|
371
|
+
address,
|
|
372
|
+
request,
|
|
373
|
+
timeoutMs: remainingTimeout(deadlineMs),
|
|
374
|
+
maxBodyBytes
|
|
375
|
+
});
|
|
376
|
+
assertCimdResponse(response, maxBodyBytes);
|
|
377
|
+
return {
|
|
378
|
+
metadata: parseCimdDocument(response.body, clientId),
|
|
379
|
+
cacheMaxAgeSeconds: parseCacheMaxAge(response.headers)
|
|
380
|
+
};
|
|
381
|
+
} catch (error) {
|
|
382
|
+
if (error instanceof OAuthMetadataFetchError && error.reason === 'connection-failed' && index < addresses.length - 1) {
|
|
383
|
+
lastConnectionError = error;
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
throw error;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
throw lastConnectionError ?? metadataFetchError('connection-failed');
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
//# sourceMappingURL=cimd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/cimd.ts"],"sourcesContent":["import {promises as dnsPromises} from 'node:dns';\nimport type {IncomingMessage} from 'node:http';\nimport {request as httpsRequest} from 'node:https';\nimport {isIP} from 'node:net';\nimport {oauthClientMetadataDocumentSchema} from '@shipfox/api-auth-dto';\nimport {InvalidOAuthClientMetadataError, OAuthMetadataFetchError} from './errors.js';\nimport type {ValidatedOAuthClientMetadata} from './oauth-client.js';\nimport {\n OAUTH_CIMD_CACHE_MAX_AGE_SECONDS,\n validateOAuthClientId,\n validateOAuthClientMetadataDocument,\n} from './oauth-client.js';\n\nexport const OAUTH_CIMD_MAX_BODY_BYTES = 256 * 1024;\nexport const OAUTH_CIMD_FETCH_TIMEOUT_MS = 5_000;\n\nconst DECIMAL_RE = /^\\d+$/u;\nconst IPV6_GROUP_RE = /^[0-9a-f]{1,4}$/u;\n\nclass CimdTimeoutError extends Error {\n constructor() {\n super('CIMD fetch timed out');\n this.name = 'CimdTimeoutError';\n }\n}\n\nexport interface CimdAddress {\n address: string;\n family: 4 | 6;\n}\n\nexport interface CimdHttpResponse {\n statusCode: number;\n headers: Record<string, string | string[] | undefined>;\n body: Uint8Array;\n}\n\nexport type CimdAddressResolver = (hostname: string) => Promise<readonly CimdAddress[]>;\nexport type CimdHttpRequester = (params: {\n url: URL;\n address: CimdAddress;\n timeoutMs: number;\n maxBodyBytes: number;\n signal?: AbortSignal;\n}) => Promise<CimdHttpResponse>;\n\nexport interface FetchedCimdMetadata {\n metadata: ValidatedOAuthClientMetadata;\n cacheMaxAgeSeconds: number;\n}\n\nfunction metadataFetchError(\n reason: OAuthMetadataFetchError['reason'],\n cause?: unknown,\n): OAuthMetadataFetchError {\n return new OAuthMetadataFetchError(reason, cause);\n}\n\nfunction ipv4ToNumber(value: string): number | undefined {\n const parts = value.split('.');\n if (parts.length !== 4) return undefined;\n let result = 0;\n for (const part of parts) {\n if (!DECIMAL_RE.test(part)) return undefined;\n const octet = Number(part);\n if (!Number.isInteger(octet) || octet > 255) return undefined;\n result = result * 256 + octet;\n }\n return result >>> 0;\n}\n\nfunction inIpv4Range(value: number, start: number, end: number): boolean {\n return value >= start && value <= end;\n}\n\nfunction isPublicIpv4(value: string): boolean {\n const address = ipv4ToNumber(value);\n if (address === undefined) return false;\n return !(\n (\n inIpv4Range(address, 0x00000000, 0x00ffffff) || // 0.0.0.0/8\n inIpv4Range(address, 0x0a000000, 0x0affffff) || // 10.0.0.0/8\n inIpv4Range(address, 0x64400000, 0x647fffff) || // 100.64.0.0/10\n inIpv4Range(address, 0x7f000000, 0x7fffffff) || // 127.0.0.0/8\n inIpv4Range(address, 0xa9fe0000, 0xa9feffff) || // 169.254.0.0/16\n inIpv4Range(address, 0xac100000, 0xac1fffff) || // 172.16.0.0/12\n inIpv4Range(address, 0xc0000000, 0xc00000ff) || // 192.0.0.0/24\n inIpv4Range(address, 0xc0000200, 0xc00002ff) || // 192.0.2.0/24\n inIpv4Range(address, 0xc01fc400, 0xc01fc4ff) || // 192.31.196.0/24\n inIpv4Range(address, 0xc034c100, 0xc034c1ff) || // 192.52.193.0/24\n inIpv4Range(address, 0xc0586300, 0xc05863ff) || // 192.88.99.0/24\n inIpv4Range(address, 0xc0a80000, 0xc0a8ffff) || // 192.168.0.0/16\n inIpv4Range(address, 0xc0af3000, 0xc0af30ff) || // 192.175.48.0/24\n inIpv4Range(address, 0xc6120000, 0xc613ffff) || // 198.18.0.0/15\n inIpv4Range(address, 0xc6336400, 0xc63364ff) || // 198.51.100.0/24\n inIpv4Range(address, 0xcb007100, 0xcb0071ff) || // 203.0.113.0/24\n inIpv4Range(address, 0xe0000000, 0xffffffff)\n ) // multicast, reserved, broadcast\n );\n}\n\nfunction parseIpv6(value: string): bigint[] | undefined {\n if (value.includes('%')) return undefined;\n const input = expandEmbeddedIpv4(value.toLowerCase());\n if (input === undefined) return undefined;\n\n const parts = splitIpv6Groups(input);\n if (parts === undefined) return undefined;\n const {left, right, hasCompression} = parts;\n\n const groups = hasCompression\n ? [...left, ...Array(8 - left.length - right.length).fill('0'), ...right]\n : [...left, ...right];\n if (groups.length !== 8) return undefined;\n return groups.map((part) => BigInt(`0x${part}`));\n}\n\nfunction expandEmbeddedIpv4(value: string): string | undefined {\n if (!value.includes('.')) return value;\n const lastColon = value.lastIndexOf(':');\n if (lastColon < 0) return undefined;\n const ipv4 = ipv4ToNumber(value.slice(lastColon + 1));\n if (ipv4 === undefined) return undefined;\n const high = ((ipv4 >>> 16) & 0xffff).toString(16);\n const low = (ipv4 & 0xffff).toString(16);\n return `${value.slice(0, lastColon)}:${high}:${low}`;\n}\n\nfunction splitIpv6Groups(value: string):\n | {\n hasCompression: boolean;\n left: string[];\n right: string[];\n }\n | undefined {\n const compressionStart = value.indexOf('::');\n if (compressionStart !== -1 && compressionStart !== value.lastIndexOf('::')) {\n return undefined;\n }\n\n const hasCompression = compressionStart !== -1;\n const [leftText, rightText = ''] = value.split('::');\n const left = leftText ? leftText.split(':') : [];\n const right = rightText ? rightText.split(':') : [];\n if (left.some((part) => !IPV6_GROUP_RE.test(part))) return undefined;\n if (right.some((part) => !IPV6_GROUP_RE.test(part))) return undefined;\n if (!hasCompression && left.length + right.length !== 8) return undefined;\n if (hasCompression && left.length + right.length >= 8) return undefined;\n return {hasCompression, left, right};\n}\n\nfunction isPublicIpv6(value: string): boolean {\n const groups = parseIpv6(value);\n if (!groups) return false;\n const first = Number(groups[0]);\n if (first < 0x2000 || first > 0x3fff) return false;\n\n // Keep documentation, benchmarking, transition, and other special-use\n // prefixes out of a fetch path even when a resolver returns a routable one.\n if (first === 0x2001) {\n const second = Number(groups[1]);\n if (\n second === 0x0000 ||\n second === 0x0002 ||\n (second >= 0x0010 && second <= 0x002f) ||\n (second >= 0x0db8 && second <= 0x0dbf)\n ) {\n return false;\n }\n }\n if (first === 0x2002 || first === 0x3fff) return false;\n return true;\n}\n\n/** Returns true only for a globally routable unicast address. */\nexport function isPublicUnicastAddress(address: string, family?: 4 | 6): boolean {\n const normalized = address.replace(/^\\[|\\]$/gu, '');\n const detectedFamily = family ?? (isIP(normalized) as 4 | 6 | 0);\n if (detectedFamily === 4) return isPublicIpv4(normalized);\n if (detectedFamily === 6) return isPublicIpv6(normalized);\n return false;\n}\n\nfunction normalizeHostname(url: URL): string {\n return url.hostname.replace(/^\\[|\\]$/gu, '');\n}\n\nasync function resolvePublicAddress(hostname: string): Promise<readonly CimdAddress[]> {\n if (isIP(hostname) === 4 || isIP(hostname) === 6) {\n const family = isIP(hostname) as 4 | 6;\n if (!isPublicUnicastAddress(hostname, family)) {\n throw metadataFetchError('private-address');\n }\n return [{address: hostname, family}];\n }\n\n let resolved: Array<{address: string; family: number}>;\n try {\n resolved = await dnsPromises.lookup(hostname, {all: true, verbatim: true});\n } catch (error) {\n throw metadataFetchError('dns-failed', error);\n }\n if (resolved.length === 0) throw metadataFetchError('dns-failed');\n\n const addresses = resolved.map((entry) => ({\n address: entry.address,\n family: entry.family as 4 | 6,\n }));\n if (\n addresses.some(\n (entry) =>\n (entry.family !== 4 && entry.family !== 6) ||\n !isPublicUnicastAddress(entry.address, entry.family),\n )\n ) {\n throw metadataFetchError('private-address');\n }\n return addresses;\n}\n\nfunction headerValue(\n headers: Record<string, string | string[] | undefined>,\n name: string,\n): string | undefined {\n const normalizedName = name.toLowerCase();\n const headerName = Object.keys(headers).find((key) => key.toLowerCase() === normalizedName);\n const value = headerName === undefined ? undefined : headers[headerName];\n if (Array.isArray(value)) return value.join(', ');\n return value;\n}\n\nfunction parseCacheMaxAge(headers: Record<string, string | string[] | undefined>): number {\n const cacheControl = headerValue(headers, 'cache-control');\n if (!cacheControl) return OAUTH_CIMD_CACHE_MAX_AGE_SECONDS;\n\n let maxAge: number | undefined;\n for (const directive of cacheControl.split(',')) {\n const [rawName, rawValue] = directive.trim().split('=', 2);\n const name = rawName?.trim().toLowerCase();\n if (name === 'no-store' || name === 'no-cache') return 0;\n if (name === 'max-age' && rawValue !== undefined && DECIMAL_RE.test(rawValue.trim())) {\n maxAge = Number(rawValue.trim());\n }\n }\n return Math.min(maxAge ?? OAUTH_CIMD_CACHE_MAX_AGE_SECONDS, OAUTH_CIMD_CACHE_MAX_AGE_SECONDS);\n}\n\nfunction withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n onTimeout?: () => void,\n): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n let settled = false;\n const timer = setTimeout(() => {\n if (settled) return;\n settled = true;\n onTimeout?.();\n reject(new CimdTimeoutError());\n }, timeoutMs);\n promise.then(\n (value) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n resolve(value);\n },\n (error: unknown) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n reject(error);\n },\n );\n });\n}\n\nfunction requestPinnedHttps(params: {\n url: URL;\n address: CimdAddress;\n timeoutMs: number;\n maxBodyBytes: number;\n signal?: AbortSignal;\n}): Promise<CimdHttpResponse> {\n return new Promise((resolve, reject) => {\n const hostname = normalizeHostname(params.url);\n let settled = false;\n\n const fail = (error: unknown) => {\n if (settled) return;\n settled = true;\n reject(error);\n };\n const succeed = (response: CimdHttpResponse) => {\n if (settled) return;\n settled = true;\n resolve(response);\n };\n\n if (params.url.protocol !== 'https:' || params.url.username || params.url.password) {\n fail(metadataFetchError('invalid-url'));\n return;\n }\n\n const request = httpsRequest(\n {\n hostname,\n port: params.url.port || 443,\n path: `${params.url.pathname || '/'}${params.url.search}`,\n method: 'GET',\n headers: {accept: 'application/json'},\n rejectUnauthorized: true,\n servername: hostname,\n timeout: params.timeoutMs,\n signal: params.signal,\n // The address was resolved before this request and is the only value\n // the TLS connection is allowed to use.\n lookup: (_lookupHostname, _options, callback) => {\n callback(null, params.address.address, params.address.family);\n },\n },\n (response) => {\n handleCimdResponse(response, params.maxBodyBytes, fail, succeed);\n },\n );\n request.once('error', (error) => fail(error));\n request.once('timeout', () => {\n request.destroy();\n fail(metadataFetchError('timeout'));\n });\n request.end();\n });\n}\n\nfunction responseHeaderError(\n statusCode: number | undefined,\n headers: Record<string, string | string[] | undefined>,\n maxBodyBytes: number,\n): OAuthMetadataFetchError | undefined {\n if (statusCode !== undefined && statusCode >= 300 && statusCode < 400) {\n return metadataFetchError('redirected');\n }\n const contentLength = headerValue(headers, 'content-length');\n if (contentLength !== undefined) {\n if (!DECIMAL_RE.test(contentLength.trim())) return metadataFetchError('invalid-response');\n if (Number(contentLength) > maxBodyBytes) return metadataFetchError('response-too-large');\n }\n const contentEncoding = headerValue(headers, 'content-encoding');\n if (contentEncoding && contentEncoding.toLowerCase() !== 'identity') {\n return metadataFetchError('invalid-response');\n }\n return undefined;\n}\n\nfunction readCimdResponseBody(response: IncomingMessage, maxBodyBytes: number): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n response.on('data', (chunk: Buffer | string) => {\n const buffer = typeof chunk === 'string' ? Buffer.from(chunk) : chunk;\n size += buffer.byteLength;\n if (size > maxBodyBytes) {\n response.destroy();\n reject(metadataFetchError('response-too-large'));\n return;\n }\n chunks.push(buffer);\n });\n response.once('error', reject);\n response.once('end', () => resolve(Buffer.concat(chunks)));\n });\n}\n\nfunction handleCimdResponse(\n response: IncomingMessage,\n maxBodyBytes: number,\n fail: (error: unknown) => void,\n succeed: (response: CimdHttpResponse) => void,\n): void {\n const headers: Record<string, string | string[] | undefined> = response.headers;\n const headerError = responseHeaderError(response.statusCode, headers, maxBodyBytes);\n if (headerError) {\n response.destroy();\n fail(headerError);\n return;\n }\n void readCimdResponseBody(response, maxBodyBytes).then(\n (body) => succeed({statusCode: response.statusCode ?? 0, headers, body}),\n fail,\n );\n}\n\nfunction parseCimdDocument(body: Uint8Array, clientId: string): ValidatedOAuthClientMetadata {\n let parsed: unknown;\n try {\n parsed = JSON.parse(Buffer.from(body).toString('utf8'));\n } catch {\n throw new InvalidOAuthClientMetadataError();\n }\n\n const result = oauthClientMetadataDocumentSchema.safeParse(parsed);\n if (!result.success) throw new InvalidOAuthClientMetadataError();\n return validateOAuthClientMetadataDocument(result.data, clientId);\n}\n\nasync function resolvePinnedAddresses(\n hostname: string,\n resolveAddress: CimdAddressResolver,\n timeoutMs: number,\n): Promise<readonly CimdAddress[]> {\n let resolved: readonly CimdAddress[];\n try {\n resolved = await withTimeout(resolveAddress(hostname), timeoutMs);\n } catch (error) {\n if (error instanceof OAuthMetadataFetchError) throw error;\n if (error instanceof CimdTimeoutError) throw metadataFetchError('timeout', error);\n throw metadataFetchError('dns-failed', error);\n }\n if (resolved.length === 0) throw metadataFetchError('dns-failed');\n if (\n resolved.some(\n (entry) =>\n (entry.family !== 4 && entry.family !== 6) ||\n !isPublicUnicastAddress(entry.address, entry.family),\n )\n ) {\n throw metadataFetchError('private-address');\n }\n return resolved;\n}\n\nasync function requestCimdResponse(params: {\n url: URL;\n address: CimdAddress;\n request: CimdHttpRequester;\n timeoutMs: number;\n maxBodyBytes: number;\n}): Promise<CimdHttpResponse> {\n const abortController = new AbortController();\n try {\n return await withTimeout(\n params.request({\n url: params.url,\n address: params.address,\n timeoutMs: params.timeoutMs,\n maxBodyBytes: params.maxBodyBytes,\n signal: abortController.signal,\n }),\n params.timeoutMs,\n () => abortController.abort(),\n );\n } catch (error) {\n if (error instanceof OAuthMetadataFetchError) throw error;\n if (error instanceof CimdTimeoutError) throw metadataFetchError('timeout', error);\n throw metadataFetchError('connection-failed', error);\n }\n}\n\nfunction remainingTimeout(deadlineMs: number): number {\n const timeoutMs = deadlineMs - Date.now();\n if (timeoutMs <= 0) throw metadataFetchError('timeout');\n return timeoutMs;\n}\n\nfunction assertCimdResponse(response: CimdHttpResponse, maxBodyBytes: number): void {\n const headerError = responseHeaderError(response.statusCode, response.headers, maxBodyBytes);\n if (headerError) throw headerError;\n if (response.statusCode !== 200) throw metadataFetchError('invalid-response');\n if (response.body.byteLength > maxBodyBytes) {\n throw metadataFetchError('response-too-large');\n }\n}\n\nexport interface FetchCimdMetadataOptions {\n resolveAddress?: CimdAddressResolver;\n request?: CimdHttpRequester;\n timeoutMs?: number;\n maxBodyBytes?: number;\n}\n\n/**\n * Fetches a Client ID Metadata Document after resolving and pinning a public\n * address. This deliberately does not share the general egress helper: CIMD\n * has stricter public-only, no-redirect, and no-credential requirements.\n */\nexport async function fetchClientIdMetadata(\n clientId: string,\n options: FetchCimdMetadataOptions = {},\n): Promise<FetchedCimdMetadata> {\n const url = validateOAuthClientId(clientId);\n const timeoutMs = options.timeoutMs ?? OAUTH_CIMD_FETCH_TIMEOUT_MS;\n const maxBodyBytes = options.maxBodyBytes ?? OAUTH_CIMD_MAX_BODY_BYTES;\n const resolveAddress = options.resolveAddress ?? resolvePublicAddress;\n const request = options.request ?? requestPinnedHttps;\n const hostname = normalizeHostname(url);\n const deadlineMs = Date.now() + timeoutMs;\n\n const addresses = await resolvePinnedAddresses(\n hostname,\n resolveAddress,\n remainingTimeout(deadlineMs),\n );\n let lastConnectionError: OAuthMetadataFetchError | undefined;\n for (const [index, address] of addresses.entries()) {\n try {\n const response = await requestCimdResponse({\n url,\n address,\n request,\n timeoutMs: remainingTimeout(deadlineMs),\n maxBodyBytes,\n });\n assertCimdResponse(response, maxBodyBytes);\n\n return {\n metadata: parseCimdDocument(response.body, clientId),\n cacheMaxAgeSeconds: parseCacheMaxAge(response.headers),\n };\n } catch (error) {\n if (\n error instanceof OAuthMetadataFetchError &&\n error.reason === 'connection-failed' &&\n index < addresses.length - 1\n ) {\n lastConnectionError = error;\n continue;\n }\n throw error;\n }\n }\n throw lastConnectionError ?? metadataFetchError('connection-failed');\n}\n"],"names":["promises","dnsPromises","request","httpsRequest","isIP","oauthClientMetadataDocumentSchema","InvalidOAuthClientMetadataError","OAuthMetadataFetchError","OAUTH_CIMD_CACHE_MAX_AGE_SECONDS","validateOAuthClientId","validateOAuthClientMetadataDocument","OAUTH_CIMD_MAX_BODY_BYTES","OAUTH_CIMD_FETCH_TIMEOUT_MS","DECIMAL_RE","IPV6_GROUP_RE","CimdTimeoutError","Error","name","metadataFetchError","reason","cause","ipv4ToNumber","value","parts","split","length","undefined","result","part","test","octet","Number","isInteger","inIpv4Range","start","end","isPublicIpv4","address","parseIpv6","includes","input","expandEmbeddedIpv4","toLowerCase","splitIpv6Groups","left","right","hasCompression","groups","Array","fill","map","BigInt","lastColon","lastIndexOf","ipv4","slice","high","toString","low","compressionStart","indexOf","leftText","rightText","some","isPublicIpv6","first","second","isPublicUnicastAddress","family","normalized","replace","detectedFamily","normalizeHostname","url","hostname","resolvePublicAddress","resolved","lookup","all","verbatim","error","addresses","entry","headerValue","headers","normalizedName","headerName","Object","keys","find","key","isArray","join","parseCacheMaxAge","cacheControl","maxAge","directive","rawName","rawValue","trim","Math","min","withTimeout","promise","timeoutMs","onTimeout","Promise","resolve","reject","settled","timer","setTimeout","then","clearTimeout","requestPinnedHttps","params","fail","succeed","response","protocol","username","password","port","path","pathname","search","method","accept","rejectUnauthorized","servername","timeout","signal","_lookupHostname","_options","callback","handleCimdResponse","maxBodyBytes","once","destroy","responseHeaderError","statusCode","contentLength","contentEncoding","readCimdResponseBody","chunks","size","on","chunk","buffer","Buffer","from","byteLength","push","concat","headerError","body","parseCimdDocument","clientId","parsed","JSON","parse","safeParse","success","data","resolvePinnedAddresses","resolveAddress","requestCimdResponse","abortController","AbortController","abort","remainingTimeout","deadlineMs","Date","now","assertCimdResponse","fetchClientIdMetadata","options","lastConnectionError","index","entries","metadata","cacheMaxAgeSeconds"],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export type AgentClientKind = 'registered' | 'cimd';
|
|
2
|
+
export interface AgentClient {
|
|
3
|
+
id: string;
|
|
4
|
+
clientId: string;
|
|
5
|
+
name: string;
|
|
6
|
+
redirectUris: string[];
|
|
7
|
+
kind: AgentClientKind;
|
|
8
|
+
lastSeenAt: Date | null;
|
|
9
|
+
unreferencedAt: Date | null;
|
|
10
|
+
createdAt: Date;
|
|
11
|
+
updatedAt: Date;
|
|
12
|
+
}
|
|
13
|
+
export interface AgentAuthorizationRequest {
|
|
14
|
+
id: string;
|
|
15
|
+
clientId: string;
|
|
16
|
+
redirectUri: string;
|
|
17
|
+
resource: string;
|
|
18
|
+
scopes: string[];
|
|
19
|
+
codeChallenge: string;
|
|
20
|
+
state: string | null;
|
|
21
|
+
expiresAt: Date;
|
|
22
|
+
consumedAt: Date | null;
|
|
23
|
+
createdAt: Date;
|
|
24
|
+
updatedAt: Date;
|
|
25
|
+
}
|
|
26
|
+
export interface AgentGrant {
|
|
27
|
+
id: string;
|
|
28
|
+
userId: string;
|
|
29
|
+
workspaceId: string;
|
|
30
|
+
clientId: string;
|
|
31
|
+
scopes: string[];
|
|
32
|
+
lastUsedAt: Date | null;
|
|
33
|
+
revokedAt: Date | null;
|
|
34
|
+
terminalAt: Date | null;
|
|
35
|
+
createdAt: Date;
|
|
36
|
+
updatedAt: Date;
|
|
37
|
+
}
|
|
38
|
+
export interface AgentAuthorizationCode {
|
|
39
|
+
id: string;
|
|
40
|
+
grantId: string;
|
|
41
|
+
hashedCode: string;
|
|
42
|
+
codeChallenge: string;
|
|
43
|
+
redirectUri: string;
|
|
44
|
+
resource: string;
|
|
45
|
+
expiresAt: Date;
|
|
46
|
+
consumedAt: Date | null;
|
|
47
|
+
createdAt: Date;
|
|
48
|
+
updatedAt: Date;
|
|
49
|
+
}
|
|
50
|
+
export interface AgentRefreshToken {
|
|
51
|
+
id: string;
|
|
52
|
+
grantId: string;
|
|
53
|
+
hashedToken: string;
|
|
54
|
+
expiresAt: Date;
|
|
55
|
+
rotatedAt: Date | null;
|
|
56
|
+
revokedAt: Date | null;
|
|
57
|
+
lastUsedAt: Date | null;
|
|
58
|
+
createdAt: Date;
|
|
59
|
+
updatedAt: Date;
|
|
60
|
+
}
|
|
61
|
+
export interface AgentPersonalAccessToken {
|
|
62
|
+
id: string;
|
|
63
|
+
userId: string;
|
|
64
|
+
workspaceId: string;
|
|
65
|
+
hashedToken: string;
|
|
66
|
+
prefix: string;
|
|
67
|
+
name: string;
|
|
68
|
+
scopes: string[];
|
|
69
|
+
expiresAt: Date;
|
|
70
|
+
lastUsedAt: Date | null;
|
|
71
|
+
revokedAt: Date | null;
|
|
72
|
+
createdAt: Date;
|
|
73
|
+
updatedAt: Date;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=agent-access.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-access.d.ts","sourceRoot":"","sources":["../../../src/core/entities/agent-access.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,IAAI,EAAE,eAAe,CAAC;IACtB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,IAAI,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/entities/agent-access.ts"],"sourcesContent":["export type AgentClientKind = 'registered' | 'cimd';\n\nexport interface AgentClient {\n id: string;\n clientId: string;\n name: string;\n redirectUris: string[];\n kind: AgentClientKind;\n lastSeenAt: Date | null;\n unreferencedAt: Date | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface AgentAuthorizationRequest {\n id: string;\n clientId: string;\n redirectUri: string;\n resource: string;\n scopes: string[];\n codeChallenge: string;\n state: string | null;\n expiresAt: Date;\n consumedAt: Date | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface AgentGrant {\n id: string;\n userId: string;\n workspaceId: string;\n clientId: string;\n scopes: string[];\n lastUsedAt: Date | null;\n revokedAt: Date | null;\n terminalAt: Date | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface AgentAuthorizationCode {\n id: string;\n grantId: string;\n hashedCode: string;\n codeChallenge: string;\n redirectUri: string;\n resource: string;\n expiresAt: Date;\n consumedAt: Date | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface AgentRefreshToken {\n id: string;\n grantId: string;\n hashedToken: string;\n expiresAt: Date;\n rotatedAt: Date | null;\n revokedAt: Date | null;\n lastUsedAt: Date | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface AgentPersonalAccessToken {\n id: string;\n userId: string;\n workspaceId: string;\n hashedToken: string;\n prefix: string;\n name: string;\n scopes: string[];\n expiresAt: Date;\n lastUsedAt: Date | null;\n revokedAt: Date | null;\n createdAt: Date;\n updatedAt: Date;\n}\n"],"names":[],"mappings":"AAkEA,WAaC"}
|
package/dist/core/errors.d.ts
CHANGED
|
@@ -39,6 +39,9 @@ export declare class AdminRoleRequiredError extends Error {
|
|
|
39
39
|
readonly minimumRole: import('@shipfox/api-auth-dto').AdminRole;
|
|
40
40
|
constructor(minimumRole: import('@shipfox/api-auth-dto').AdminRole);
|
|
41
41
|
}
|
|
42
|
+
export declare class InvalidAdministratorUserDirectoryFilterError extends Error {
|
|
43
|
+
constructor(message: string);
|
|
44
|
+
}
|
|
42
45
|
export declare class LastAdminOwnerError extends Error {
|
|
43
46
|
constructor();
|
|
44
47
|
}
|
|
@@ -93,4 +96,18 @@ export declare class InvitationEmailMismatchError extends Error {
|
|
|
93
96
|
export declare class OpenInvitationExistsError extends Error {
|
|
94
97
|
constructor(email: string);
|
|
95
98
|
}
|
|
99
|
+
export declare class InvalidOAuthClientMetadataError extends Error {
|
|
100
|
+
constructor();
|
|
101
|
+
}
|
|
102
|
+
export declare class OAuthRedirectUriNotRegisteredError extends Error {
|
|
103
|
+
constructor();
|
|
104
|
+
}
|
|
105
|
+
export declare class OAuthMetadataFetchError extends Error {
|
|
106
|
+
readonly reason: 'invalid-url' | 'private-address' | 'dns-failed' | 'connection-failed' | 'redirected' | 'timeout' | 'response-too-large' | 'invalid-response';
|
|
107
|
+
readonly cause: unknown;
|
|
108
|
+
constructor(reason: OAuthMetadataFetchError['reason'], cause?: unknown);
|
|
109
|
+
}
|
|
110
|
+
export declare class InvalidOAuthConfigurationError extends Error {
|
|
111
|
+
constructor();
|
|
112
|
+
}
|
|
96
113
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,YAAY,CAAC;AAE1D,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,YAAY,WAAW,EAAE,MAAM,EAG9B;CACF;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,EAAE,EAAE,MAAM,EAGrB;CACF;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,YAAY,EAAE,EAAE,MAAM,EAGrB;CACF;AAED,qBAAa,gCAAiC,SAAQ,KAAK;IACzD,cAGC;CACF;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,YAAY,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAG9C;CACF;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,YAAY,SAAS,EAAE,MAAM,EAG5B;CACF;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,YAAY,KAAK,EAAE,MAAM,EAGxB;CACF;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAG5C,QAAQ,CAAC,MAAM,CAAC,EAAE,yBAAyB;IAF7C,YACE,OAAO,EAAE,MAAM,EACN,MAAM,CAAC,EAAE,yBAAyB,YAAA,EAI5C;CACF;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,cAGC;CACF;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,cAGC;CACF;AAED,qBAAa,8BAA+B,SAAQ,KAAK;IACvD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,SAAkB,KAAK,EAAE,OAAO,CAAC;IAEjC,YAAY,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAK7C;CACF;AAED,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,WAAW,EAAE,OAAO,uBAAuB,EAAE,SAAS,CAAC;IAEhE,YAAY,WAAW,EAAE,OAAO,uBAAuB,EAAE,SAAS,EAIjE;CACF;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,cAGC;CACF;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,cAGC;CACF;AAED,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,cAGC;CACF;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,cAGC;CACF;AAED,qBAAa,+BAAgC,SAAQ,KAAK;IACxD,cAGC;CACF;AAED,qBAAa,6BAA8B,SAAQ,KAAK;IACtD,cAGC;CACF;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,cAGC;CACF;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,cAGC;CACF;AAED,qBAAa,mCAAoC,SAAQ,KAAK;IAC5D,cAGC;CACF;AAED,qBAAa,iCAAkC,SAAQ,KAAK;IAC1D,cAGC;CACF;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,cAGC;CACF;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,YAAY,MAAM,CAAC,EAAE,MAAM,EAG1B;CACF;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,cAGC;CACF;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,cAGC;CACF;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,YAAY,WAAW,EAAE,MAAM,EAG9B;CACF;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,YAAY,WAAW,EAAE,MAAM,EAG9B;CACF;AAED,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,cAGC;CACF;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,YAAY,KAAK,EAAE,MAAM,EAGxB;CACF"}
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/core/errors.js
CHANGED
|
@@ -73,6 +73,12 @@ export class AdminRoleRequiredError extends Error {
|
|
|
73
73
|
this.minimumRole = minimumRole;
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
+
export class InvalidAdministratorUserDirectoryFilterError extends Error {
|
|
77
|
+
constructor(message){
|
|
78
|
+
super(message);
|
|
79
|
+
this.name = 'InvalidAdministratorUserDirectoryFilterError';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
76
82
|
export class LastAdminOwnerError extends Error {
|
|
77
83
|
constructor(){
|
|
78
84
|
super('Cannot remove the final active administrator owner');
|
|
@@ -181,5 +187,31 @@ export class OpenInvitationExistsError extends Error {
|
|
|
181
187
|
this.name = 'OpenInvitationExistsError';
|
|
182
188
|
}
|
|
183
189
|
}
|
|
190
|
+
export class InvalidOAuthClientMetadataError extends Error {
|
|
191
|
+
constructor(){
|
|
192
|
+
super('OAuth client metadata is invalid');
|
|
193
|
+
this.name = 'InvalidOAuthClientMetadataError';
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
export class OAuthRedirectUriNotRegisteredError extends Error {
|
|
197
|
+
constructor(){
|
|
198
|
+
super('OAuth redirect URI is not registered');
|
|
199
|
+
this.name = 'OAuthRedirectUriNotRegisteredError';
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
export class OAuthMetadataFetchError extends Error {
|
|
203
|
+
constructor(reason, cause){
|
|
204
|
+
super('OAuth client metadata could not be fetched');
|
|
205
|
+
this.name = 'OAuthMetadataFetchError';
|
|
206
|
+
this.reason = reason;
|
|
207
|
+
this.cause = cause;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
export class InvalidOAuthConfigurationError extends Error {
|
|
211
|
+
constructor(){
|
|
212
|
+
super('OAuth public URL configuration is invalid');
|
|
213
|
+
this.name = 'InvalidOAuthConfigurationError';
|
|
214
|
+
}
|
|
215
|
+
}
|
|
184
216
|
|
|
185
217
|
//# sourceMappingURL=errors.js.map
|