@authyon/server 0.2.0-beta.2 → 0.2.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +165 -0
- package/dist/index.cjs +348 -26
- package/dist/index.d.cts +296 -62
- package/dist/index.d.ts +296 -62
- package/dist/index.js +346 -26
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,32 +1,287 @@
|
|
|
1
|
+
var __typeError = (msg) => {
|
|
2
|
+
throw TypeError(msg);
|
|
3
|
+
};
|
|
4
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
5
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
6
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
7
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
8
|
+
|
|
9
|
+
// src/client/credentialManagement.ts
|
|
10
|
+
function segment(value) {
|
|
11
|
+
if (typeof value !== "string" || !value.trim() || value === "." || value === ".." || [...value].some((character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127)) {
|
|
12
|
+
throw new TypeError("Authyon: invalid route identifier.");
|
|
13
|
+
}
|
|
14
|
+
return encodeURIComponent(value);
|
|
15
|
+
}
|
|
16
|
+
function permissionsBody(input) {
|
|
17
|
+
if (input.permissions !== void 0 && input.scopes !== void 0) {
|
|
18
|
+
throw new TypeError("Authyon: supply permissions or scopes, not both.");
|
|
19
|
+
}
|
|
20
|
+
const values = input.permissions ?? input.scopes;
|
|
21
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
22
|
+
throw new TypeError("Authyon: explicit credential permissions are required.");
|
|
23
|
+
}
|
|
24
|
+
const permissions = values.map((value) => {
|
|
25
|
+
if (typeof value !== "string") throw new TypeError("Authyon: invalid permission.");
|
|
26
|
+
const normalized = value.trim().toLowerCase();
|
|
27
|
+
if (!/^(?:\*|[a-z][a-z0-9_-]*):(?:\*|[a-z][a-z0-9_-]*):(?:\*|[a-z][a-z0-9_-]*)$/u.test(normalized)) {
|
|
28
|
+
throw new TypeError("Authyon: permissions must have namespace:resource:action format.");
|
|
29
|
+
}
|
|
30
|
+
return normalized;
|
|
31
|
+
});
|
|
32
|
+
return { permissions: [...new Set(permissions)] };
|
|
33
|
+
}
|
|
34
|
+
function lifetimeBody(input) {
|
|
35
|
+
if (input.lifetimeDays === void 0 || input.lifetimeDays === null) return {};
|
|
36
|
+
if (!Number.isInteger(input.lifetimeDays) || input.lifetimeDays < 1 || input.lifetimeDays > 3650) {
|
|
37
|
+
throw new RangeError("Authyon: lifetimeDays must be between 1 and 3650.");
|
|
38
|
+
}
|
|
39
|
+
return { lifetimeDays: input.lifetimeDays };
|
|
40
|
+
}
|
|
41
|
+
function credentialQuery(options = {}) {
|
|
42
|
+
const { skip, take, search } = options;
|
|
43
|
+
if (skip !== void 0 && (!Number.isInteger(skip) || skip < 0 || skip > 2147483647))
|
|
44
|
+
throw new RangeError("Authyon: invalid skip.");
|
|
45
|
+
if (take !== void 0 && (!Number.isInteger(take) || take < 1 || take > 100))
|
|
46
|
+
throw new RangeError("Authyon: take must be between 1 and 100.");
|
|
47
|
+
if (search !== void 0 && (typeof search !== "string" || search.trim().length > 200))
|
|
48
|
+
throw new RangeError("Authyon: search must contain at most 200 characters.");
|
|
49
|
+
return { search: search?.trim() || void 0, skip, take };
|
|
50
|
+
}
|
|
51
|
+
function credentialSummary(value) {
|
|
52
|
+
return {
|
|
53
|
+
id: value.id,
|
|
54
|
+
clientId: value.clientId,
|
|
55
|
+
description: value.description,
|
|
56
|
+
createdAt: value.createdAt,
|
|
57
|
+
lastUsedAt: value.lastUsedAt,
|
|
58
|
+
revokedAt: value.revokedAt,
|
|
59
|
+
expiresAt: value.expiresAt ?? null,
|
|
60
|
+
isActive: value.isActive,
|
|
61
|
+
permissions: [...value.permissions]
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function credentialDetail(value) {
|
|
65
|
+
return {
|
|
66
|
+
...credentialSummary(value),
|
|
67
|
+
createdBy: value.createdBy == null ? null : {
|
|
68
|
+
id: value.createdBy.id,
|
|
69
|
+
type: value.createdBy.type,
|
|
70
|
+
displayName: value.createdBy.displayName
|
|
71
|
+
},
|
|
72
|
+
updatedAt: value.updatedAt,
|
|
73
|
+
secretRotatedAt: value.secretRotatedAt,
|
|
74
|
+
expiresAt: value.expiresAt ?? null,
|
|
75
|
+
ageSeconds: value.ageSeconds,
|
|
76
|
+
lifetimeSeconds: value.lifetimeSeconds,
|
|
77
|
+
accessTokenLifetimeSeconds: value.accessTokenLifetimeSeconds
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async function credentialPage(request, path, options = {}) {
|
|
81
|
+
const query = credentialQuery(options);
|
|
82
|
+
const page = await request(path, { query });
|
|
83
|
+
if (!page || !Array.isArray(page.data))
|
|
84
|
+
throw new TypeError("Authyon: expected a paginated credential response.");
|
|
85
|
+
return {
|
|
86
|
+
data: page.data.map(credentialSummary),
|
|
87
|
+
...page.perPage === void 0 ? {} : { perPage: page.perPage },
|
|
88
|
+
pageSize: page.pageSize,
|
|
89
|
+
total: page.total,
|
|
90
|
+
pages: page.pages,
|
|
91
|
+
hasNext: page.hasNext,
|
|
92
|
+
hasPrev: page.hasPrev
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
async function allCredentials(request, path) {
|
|
96
|
+
const result = [];
|
|
97
|
+
const seen = /* @__PURE__ */ new Set();
|
|
98
|
+
let skip = 0;
|
|
99
|
+
for (let iteration = 0; iteration < 1e3; iteration++) {
|
|
100
|
+
const page = await request(
|
|
101
|
+
path,
|
|
102
|
+
iteration === 0 ? {} : { query: { skip, take: 100 } }
|
|
103
|
+
);
|
|
104
|
+
if (Array.isArray(page)) {
|
|
105
|
+
if (iteration !== 0)
|
|
106
|
+
throw new Error("Authyon: credential pagination changed during listing.");
|
|
107
|
+
return page.map(credentialSummary);
|
|
108
|
+
}
|
|
109
|
+
if (!page || !Array.isArray(page.data))
|
|
110
|
+
throw new TypeError("Authyon: invalid credential page.");
|
|
111
|
+
for (const row of page.data) {
|
|
112
|
+
if (seen.has(row.id))
|
|
113
|
+
throw new Error("Authyon: credential pages overlapped; retry the listing.");
|
|
114
|
+
seen.add(row.id);
|
|
115
|
+
result.push(credentialSummary(row));
|
|
116
|
+
}
|
|
117
|
+
if (!page.hasNext) return result;
|
|
118
|
+
if (page.data.length === 0) throw new Error("Authyon: credential pagination made no progress.");
|
|
119
|
+
skip += page.data.length;
|
|
120
|
+
}
|
|
121
|
+
throw new Error("Authyon: use listPage for more than 1000 credential pages.");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// src/client/scopedManagementClient.ts
|
|
125
|
+
function scopedRequest(request, source) {
|
|
126
|
+
return async (path, options = {}) => {
|
|
127
|
+
const token = typeof source === "function" ? await source() : source;
|
|
128
|
+
if (typeof token !== "string" || !token.trim() || /\s/u.test(token))
|
|
129
|
+
throw new TypeError("Authyon: a valid access token is required.");
|
|
130
|
+
return request(path, {
|
|
131
|
+
...options,
|
|
132
|
+
headers: { ...options.headers, Authorization: `Bearer ${token}` }
|
|
133
|
+
});
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function environmentPath(scope) {
|
|
137
|
+
return `/platform/workspaces/${segment(scope.workspaceId)}/environments/${segment(scope.environmentId)}`;
|
|
138
|
+
}
|
|
139
|
+
function tenantPath(scope) {
|
|
140
|
+
return `${environmentPath(scope)}/tenants/${segment(scope.tenantId)}`;
|
|
141
|
+
}
|
|
142
|
+
function credentialPath(scope) {
|
|
143
|
+
return `${scope.tenantId === void 0 ? environmentPath(scope) : tenantPath(scope)}/credentials`;
|
|
144
|
+
}
|
|
145
|
+
function workspacePath(id) {
|
|
146
|
+
return `/platform/workspaces/${segment(id)}`;
|
|
147
|
+
}
|
|
148
|
+
function workspaceRole(role) {
|
|
149
|
+
if (role !== "admin" && role !== "auditor")
|
|
150
|
+
throw new TypeError("Authyon: workspace role must be admin or auditor.");
|
|
151
|
+
return role;
|
|
152
|
+
}
|
|
153
|
+
var _request;
|
|
154
|
+
var PlatformScopedClient = class {
|
|
155
|
+
/** @hidden */
|
|
156
|
+
constructor(request, token) {
|
|
157
|
+
__privateAdd(this, _request);
|
|
158
|
+
this.credentials = {
|
|
159
|
+
list: (scope, options = {}) => credentialPage(__privateGet(this, _request), credentialPath(scope), options),
|
|
160
|
+
get: async (scope, credentialId) => credentialDetail(await __privateGet(this, _request).call(this, `${credentialPath(scope)}/${segment(credentialId)}`)),
|
|
161
|
+
create: (scope, input) => __privateGet(this, _request).call(this, credentialPath(scope), {
|
|
162
|
+
method: "POST",
|
|
163
|
+
body: { description: input.description, ...lifetimeBody(input), ...permissionsBody(input) }
|
|
164
|
+
}),
|
|
165
|
+
updatePermissions: (scope, credentialId, input) => __privateGet(this, _request).call(this, `${credentialPath(scope)}/${segment(credentialId)}/permissions`, {
|
|
166
|
+
method: "PUT",
|
|
167
|
+
body: permissionsBody(input)
|
|
168
|
+
}),
|
|
169
|
+
updateScopes: (scope, credentialId, scopes) => this.credentials.updatePermissions(scope, credentialId, { scopes }),
|
|
170
|
+
/** Returns a new secret once. API may require an explicit step-up first. */
|
|
171
|
+
rotate: (scope, credentialId) => __privateGet(this, _request).call(this, `${credentialPath(scope)}/${segment(credentialId)}/rotate`, { method: "POST" }),
|
|
172
|
+
revoke: (scope, credentialId) => __privateGet(this, _request).call(this, `${credentialPath(scope)}/${segment(credentialId)}`, { method: "DELETE" })
|
|
173
|
+
};
|
|
174
|
+
this.workspaces = {
|
|
175
|
+
team: (workspaceId) => __privateGet(this, _request).call(this, `${workspacePath(workspaceId)}/team`),
|
|
176
|
+
members: {
|
|
177
|
+
invite: (workspaceId, input) => __privateGet(this, _request).call(this, `${workspacePath(workspaceId)}/invites`, {
|
|
178
|
+
method: "POST",
|
|
179
|
+
body: { email: input.email, role: workspaceRole(input.role) }
|
|
180
|
+
}),
|
|
181
|
+
/** memberId comes from team.members; it is not the platform userId. */
|
|
182
|
+
remove: (workspaceId, memberId) => __privateGet(this, _request).call(this, `${workspacePath(workspaceId)}/members/${segment(memberId)}`, {
|
|
183
|
+
method: "DELETE"
|
|
184
|
+
}),
|
|
185
|
+
changeRole: (workspaceId, memberId, role) => __privateGet(this, _request).call(this, `${workspacePath(workspaceId)}/members/${segment(memberId)}`, {
|
|
186
|
+
method: "PATCH",
|
|
187
|
+
body: { role: workspaceRole(role) }
|
|
188
|
+
})
|
|
189
|
+
},
|
|
190
|
+
invites: {
|
|
191
|
+
create: (workspaceId, input) => this.workspaces.members.invite(workspaceId, input),
|
|
192
|
+
revoke: (workspaceId, inviteId) => __privateGet(this, _request).call(this, `${workspacePath(workspaceId)}/invites/${segment(inviteId)}`, {
|
|
193
|
+
method: "DELETE"
|
|
194
|
+
})
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
this.tenants = {
|
|
198
|
+
members: {
|
|
199
|
+
list: (scope, options = {}) => __privateGet(this, _request).call(this, `${tenantPath(scope)}/members`, { query: options }),
|
|
200
|
+
add: (scope, userId, roles) => __privateGet(this, _request).call(this, `${tenantPath(scope)}/members`, { method: "POST", body: { userId, roles } }),
|
|
201
|
+
remove: (scope, userId) => __privateGet(this, _request).call(this, `${tenantPath(scope)}/members/${segment(userId)}`, { method: "DELETE" })
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
this.auth = {
|
|
205
|
+
/** Explicitly confirms the current platform session; passwords are not retained. */
|
|
206
|
+
stepUp: (currentPassword) => __privateGet(this, _request).call(this, "/platform/auth/step-up", { method: "POST", body: { currentPassword } })
|
|
207
|
+
};
|
|
208
|
+
__privateSet(this, _request, scopedRequest(request, token));
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
_request = new WeakMap();
|
|
212
|
+
var _request2;
|
|
213
|
+
var UserScopedClient = class {
|
|
214
|
+
/** @hidden */
|
|
215
|
+
constructor(request, token) {
|
|
216
|
+
__privateAdd(this, _request2);
|
|
217
|
+
this.tenants = {
|
|
218
|
+
members: {
|
|
219
|
+
list: (tenantId, options = {}) => __privateGet(this, _request2).call(this, `/auth/tenants/${segment(tenantId)}/members`, { query: options }),
|
|
220
|
+
/** Adds an existing environment user by email; does not send an invitation email. */
|
|
221
|
+
invite: (tenantId, input) => __privateGet(this, _request2).call(this, `/auth/tenants/${segment(tenantId)}/members`, {
|
|
222
|
+
method: "POST",
|
|
223
|
+
body: { email: input.email, roles: input.roles }
|
|
224
|
+
}),
|
|
225
|
+
remove: (tenantId, userId) => __privateGet(this, _request2).call(this, `/auth/tenants/${segment(tenantId)}/members/${segment(userId)}`, {
|
|
226
|
+
method: "DELETE"
|
|
227
|
+
})
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
__privateSet(this, _request2, scopedRequest(request, token));
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
_request2 = new WeakMap();
|
|
234
|
+
var _request3;
|
|
235
|
+
var WorkspaceInvitesClient = class {
|
|
236
|
+
/** @hidden */
|
|
237
|
+
constructor(request) {
|
|
238
|
+
__privateAdd(this, _request3);
|
|
239
|
+
__privateSet(this, _request3, request);
|
|
240
|
+
}
|
|
241
|
+
preview(token) {
|
|
242
|
+
return __privateGet(this, _request3).call(this, `/platform/workspace-invites/${segment(token)}`);
|
|
243
|
+
}
|
|
244
|
+
accept(token, input = {}) {
|
|
245
|
+
return __privateGet(this, _request3).call(this, `/platform/workspace-invites/${segment(token)}/accept`, {
|
|
246
|
+
method: "POST",
|
|
247
|
+
body: { name: input.name, password: input.password }
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
_request3 = new WeakMap();
|
|
252
|
+
|
|
1
253
|
// ../../internal/core/config/defaults.ts
|
|
2
254
|
var DEFAULT_BASE_URL = "https://api.authyon.com";
|
|
3
255
|
var DEFAULT_EXPIRY_SKEW_MS = 3e4;
|
|
4
256
|
|
|
5
257
|
// ../../internal/core/auth/expiringTokenProvider.ts
|
|
258
|
+
var _token, _inFlight;
|
|
6
259
|
var ExpiringTokenProvider = class {
|
|
7
260
|
constructor(acquire, expirySkewMs = DEFAULT_EXPIRY_SKEW_MS) {
|
|
8
261
|
this.acquire = acquire;
|
|
9
262
|
this.expirySkewMs = expirySkewMs;
|
|
10
|
-
this
|
|
11
|
-
this
|
|
263
|
+
__privateAdd(this, _token, null);
|
|
264
|
+
__privateAdd(this, _inFlight, null);
|
|
12
265
|
}
|
|
13
266
|
async getAccessToken() {
|
|
14
|
-
if (this
|
|
15
|
-
return this.
|
|
267
|
+
if (__privateGet(this, _token) && Date.now() < __privateGet(this, _token).expiresAt - this.expirySkewMs) {
|
|
268
|
+
return __privateGet(this, _token).accessToken;
|
|
16
269
|
}
|
|
17
|
-
if (this
|
|
18
|
-
this
|
|
19
|
-
this
|
|
270
|
+
if (__privateGet(this, _inFlight)) return __privateGet(this, _inFlight);
|
|
271
|
+
__privateSet(this, _inFlight, this.acquire().then((token) => {
|
|
272
|
+
__privateSet(this, _token, token);
|
|
20
273
|
return token.accessToken;
|
|
21
274
|
}).finally(() => {
|
|
22
|
-
this
|
|
23
|
-
});
|
|
24
|
-
return this
|
|
275
|
+
__privateSet(this, _inFlight, null);
|
|
276
|
+
}));
|
|
277
|
+
return __privateGet(this, _inFlight);
|
|
25
278
|
}
|
|
26
279
|
clear() {
|
|
27
|
-
this
|
|
280
|
+
__privateSet(this, _token, null);
|
|
28
281
|
}
|
|
29
282
|
};
|
|
283
|
+
_token = new WeakMap();
|
|
284
|
+
_inFlight = new WeakMap();
|
|
30
285
|
|
|
31
286
|
// ../../internal/core/errors/authyonError.ts
|
|
32
287
|
var ErrorCodes = {
|
|
@@ -157,7 +412,8 @@ var FetchHttpAdapter = class {
|
|
|
157
412
|
method: request.method,
|
|
158
413
|
headers: request.headers,
|
|
159
414
|
body: request.body,
|
|
160
|
-
signal: request.signal
|
|
415
|
+
signal: request.signal,
|
|
416
|
+
redirect: "error"
|
|
161
417
|
});
|
|
162
418
|
}
|
|
163
419
|
};
|
|
@@ -209,6 +465,10 @@ function defaultHttpLogger(event) {
|
|
|
209
465
|
}
|
|
210
466
|
function sanitizeUrl(value) {
|
|
211
467
|
const url = new URL(value);
|
|
468
|
+
url.username = "";
|
|
469
|
+
url.password = "";
|
|
470
|
+
url.hash = "";
|
|
471
|
+
url.pathname = url.pathname.replace(/(\/platform\/workspace-invites\/)[^/]+/u, "$1REDACTED");
|
|
212
472
|
const queryKeys = /* @__PURE__ */ new Set();
|
|
213
473
|
url.searchParams.forEach((_value, key) => queryKeys.add(key));
|
|
214
474
|
url.search = queryKeys.size > 0 ? [...queryKeys].map((key) => `${encodeURIComponent(key)}=REDACTED`).join("&") : "";
|
|
@@ -494,8 +754,10 @@ function isRecord(value) {
|
|
|
494
754
|
}
|
|
495
755
|
|
|
496
756
|
// src/client/authyonServerClient.ts
|
|
757
|
+
var _clientSecret;
|
|
497
758
|
var AuthyonServerClient = class {
|
|
498
759
|
constructor(options = {}) {
|
|
760
|
+
__privateAdd(this, _clientSecret);
|
|
499
761
|
// ── Discovery ──────────────────────────────────────────────────────────────
|
|
500
762
|
this.discovery = {
|
|
501
763
|
/** GET /.well-known/jwks.json — the environment's public signing keys. */
|
|
@@ -531,6 +793,9 @@ var AuthyonServerClient = class {
|
|
|
531
793
|
}
|
|
532
794
|
})
|
|
533
795
|
};
|
|
796
|
+
this.workspaceInvites = new WorkspaceInvitesClient(
|
|
797
|
+
(path, options) => this.http.request(path, options)
|
|
798
|
+
);
|
|
534
799
|
// ── Environment management (users, tenants, roles, permissions, audit) ───
|
|
535
800
|
this.environment = {
|
|
536
801
|
users: {
|
|
@@ -622,6 +887,47 @@ var AuthyonServerClient = class {
|
|
|
622
887
|
)
|
|
623
888
|
},
|
|
624
889
|
tenants: {
|
|
890
|
+
credentials: {
|
|
891
|
+
/** GET /env/tenants/{tenantId}/credentials. Returns metadata only, including revoked credentials. */
|
|
892
|
+
list: (tenantId) => allCredentials(
|
|
893
|
+
(path, options) => this.request(path, { ...options, envBearer: true }),
|
|
894
|
+
`/env/tenants/${segment(tenantId)}/credentials`
|
|
895
|
+
),
|
|
896
|
+
/** Paginated searchable listing. Prefer this over loading every credential. */
|
|
897
|
+
listPage: (tenantId, options = {}) => credentialPage(
|
|
898
|
+
(path, requestOptions) => this.request(path, { ...requestOptions, envBearer: true }),
|
|
899
|
+
`/env/tenants/${segment(tenantId)}/credentials`,
|
|
900
|
+
options
|
|
901
|
+
),
|
|
902
|
+
get: async (tenantId, credentialId) => credentialDetail(
|
|
903
|
+
await this.request(
|
|
904
|
+
`/env/tenants/${segment(tenantId)}/credentials/${segment(credentialId)}`,
|
|
905
|
+
{ envBearer: true }
|
|
906
|
+
)
|
|
907
|
+
),
|
|
908
|
+
/** Explicit scopes/permissions; only issuance returns the client secret. */
|
|
909
|
+
create: (tenantId, input) => this.request(`/env/tenants/${segment(tenantId)}/credentials`, {
|
|
910
|
+
method: "POST",
|
|
911
|
+
envBearer: true,
|
|
912
|
+
body: { description: input.description, ...lifetimeBody(input), ...permissionsBody(input) }
|
|
913
|
+
}),
|
|
914
|
+
/** Returns a new secret once while keeping the same client id. */
|
|
915
|
+
rotate: (tenantId, credentialId) => this.request(
|
|
916
|
+
`/env/tenants/${segment(tenantId)}/credentials/${segment(credentialId)}/rotate`,
|
|
917
|
+
{ method: "POST", envBearer: true }
|
|
918
|
+
),
|
|
919
|
+
updatePermissions: (tenantId, credentialId, input) => this.request(
|
|
920
|
+
`/env/tenants/${segment(tenantId)}/credentials/${segment(credentialId)}/permissions`,
|
|
921
|
+
{ method: "PUT", envBearer: true, body: permissionsBody(input) }
|
|
922
|
+
),
|
|
923
|
+
updateScopes: (tenantId, credentialId, scopes) => this.environment.tenants.credentials.updatePermissions(tenantId, credentialId, {
|
|
924
|
+
scopes
|
|
925
|
+
}),
|
|
926
|
+
revoke: (tenantId, credentialId) => this.request(`/env/tenants/${segment(tenantId)}/credentials/${segment(credentialId)}`, {
|
|
927
|
+
method: "DELETE",
|
|
928
|
+
envBearer: true
|
|
929
|
+
})
|
|
930
|
+
},
|
|
625
931
|
/** GET /env/tenants — paginated, searchable list of tenants in the environment. */
|
|
626
932
|
list: (params = {}) => this.request("/env/tenants", { envBearer: true, query: params }),
|
|
627
933
|
/** POST /env/tenants — create a tenant in the environment. */
|
|
@@ -768,7 +1074,7 @@ var AuthyonServerClient = class {
|
|
|
768
1074
|
};
|
|
769
1075
|
this.envKey = options.envKey;
|
|
770
1076
|
this.clientId = options.clientId;
|
|
771
|
-
this
|
|
1077
|
+
__privateSet(this, _clientSecret, options.clientSecret);
|
|
772
1078
|
this.transport = createSharedTransport({
|
|
773
1079
|
baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
|
|
774
1080
|
allowInsecureHttp: options.allowInsecureHttp,
|
|
@@ -779,14 +1085,14 @@ var AuthyonServerClient = class {
|
|
|
779
1085
|
});
|
|
780
1086
|
this.http = new JsonHttpClient(this.transport);
|
|
781
1087
|
this.environmentTokenProvider = new ExpiringTokenProvider(async () => {
|
|
782
|
-
if (!this.clientId || !this
|
|
1088
|
+
if (!this.clientId || !__privateGet(this, _clientSecret)) {
|
|
783
1089
|
throw new Error(
|
|
784
1090
|
"Authyon: `clientId`/`clientSecret` are required for environment management calls (mint a pair in the console, under the environment's OAuth clients)."
|
|
785
1091
|
);
|
|
786
1092
|
}
|
|
787
1093
|
const token = await this.environmentAuth.token({
|
|
788
1094
|
clientId: this.clientId,
|
|
789
|
-
clientSecret: this
|
|
1095
|
+
clientSecret: __privateGet(this, _clientSecret)
|
|
790
1096
|
});
|
|
791
1097
|
return {
|
|
792
1098
|
accessToken: token.access_token,
|
|
@@ -855,6 +1161,14 @@ var AuthyonServerClient = class {
|
|
|
855
1161
|
tenant(credentials) {
|
|
856
1162
|
return new TenantScopedClient(this, credentials);
|
|
857
1163
|
}
|
|
1164
|
+
/** Uses only the supplied platform-user access token. */
|
|
1165
|
+
platform(token) {
|
|
1166
|
+
return new PlatformScopedClient((path, options) => this.http.request(path, options), token);
|
|
1167
|
+
}
|
|
1168
|
+
/** Uses an end-user token; the configured environment key selects the environment. */
|
|
1169
|
+
user(token) {
|
|
1170
|
+
return new UserScopedClient((path, options) => this.request(path, options), token);
|
|
1171
|
+
}
|
|
858
1172
|
/** @internal used by {@link TenantScopedClient} to share the base URL/fetch/error handling. */
|
|
859
1173
|
_requestAsTenant(accessToken, path, options = {}) {
|
|
860
1174
|
return this.request(path, {
|
|
@@ -864,6 +1178,7 @@ var AuthyonServerClient = class {
|
|
|
864
1178
|
});
|
|
865
1179
|
}
|
|
866
1180
|
};
|
|
1181
|
+
_clientSecret = new WeakMap();
|
|
867
1182
|
var TenantScopedClient = class {
|
|
868
1183
|
constructor(server, credentials) {
|
|
869
1184
|
this.members = {
|
|
@@ -942,40 +1257,42 @@ function createClient(options = {}) {
|
|
|
942
1257
|
}
|
|
943
1258
|
|
|
944
1259
|
// src/client/authyonServerClientBuilder.ts
|
|
1260
|
+
var _options;
|
|
945
1261
|
var AuthyonServerClientBuilder = class {
|
|
946
1262
|
constructor() {
|
|
947
|
-
this
|
|
1263
|
+
__privateAdd(this, _options, {});
|
|
948
1264
|
}
|
|
949
1265
|
withEnvironmentKey(envKey) {
|
|
950
|
-
this.
|
|
1266
|
+
__privateGet(this, _options).envKey = envKey;
|
|
951
1267
|
return this;
|
|
952
1268
|
}
|
|
953
1269
|
withEnvironmentCredentials(clientId, clientSecret) {
|
|
954
|
-
this.
|
|
955
|
-
this.
|
|
1270
|
+
__privateGet(this, _options).clientId = clientId;
|
|
1271
|
+
__privateGet(this, _options).clientSecret = clientSecret;
|
|
956
1272
|
return this;
|
|
957
1273
|
}
|
|
958
1274
|
withBaseUrl(baseUrl, allowInsecureHttp = false) {
|
|
959
|
-
this.
|
|
960
|
-
this.
|
|
1275
|
+
__privateGet(this, _options).baseUrl = baseUrl;
|
|
1276
|
+
__privateGet(this, _options).allowInsecureHttp = allowInsecureHttp;
|
|
961
1277
|
return this;
|
|
962
1278
|
}
|
|
963
1279
|
withTimeout(timeoutMs) {
|
|
964
|
-
this.
|
|
1280
|
+
__privateGet(this, _options).timeoutMs = timeoutMs;
|
|
965
1281
|
return this;
|
|
966
1282
|
}
|
|
967
1283
|
withHttpAdapter(httpAdapter) {
|
|
968
|
-
this.
|
|
1284
|
+
__privateGet(this, _options).httpAdapter = httpAdapter;
|
|
969
1285
|
return this;
|
|
970
1286
|
}
|
|
971
1287
|
withHttpLogger(httpLogger) {
|
|
972
|
-
this.
|
|
1288
|
+
__privateGet(this, _options).httpLogger = httpLogger;
|
|
973
1289
|
return this;
|
|
974
1290
|
}
|
|
975
1291
|
build() {
|
|
976
|
-
return new AuthyonServerClient({ ...this
|
|
1292
|
+
return new AuthyonServerClient({ ...__privateGet(this, _options) });
|
|
977
1293
|
}
|
|
978
1294
|
};
|
|
1295
|
+
_options = new WeakMap();
|
|
979
1296
|
|
|
980
1297
|
// ../../internal/core/authorization/ability.ts
|
|
981
1298
|
var AuthyonAbility = class {
|
|
@@ -1085,7 +1402,7 @@ function matchesToken(value, expected, wildcard) {
|
|
|
1085
1402
|
function matchesSegments(pattern, value) {
|
|
1086
1403
|
const patternSegments = pattern.split(":");
|
|
1087
1404
|
const valueSegments = value.split(":");
|
|
1088
|
-
return patternSegments.length === valueSegments.length && patternSegments.every((
|
|
1405
|
+
return patternSegments.length === valueSegments.length && patternSegments.every((segment2, index) => segment2 === "*" || segment2 === valueSegments[index]);
|
|
1089
1406
|
}
|
|
1090
1407
|
function matchesField(pattern, field) {
|
|
1091
1408
|
if (pattern === "*" || pattern === field) return true;
|
|
@@ -1289,8 +1606,11 @@ export {
|
|
|
1289
1606
|
FetchHttpAdapter,
|
|
1290
1607
|
JwksTokenVerifier,
|
|
1291
1608
|
LoggingHttpAdapter,
|
|
1609
|
+
PlatformScopedClient,
|
|
1292
1610
|
TenantScopedClient,
|
|
1293
1611
|
TokenVerificationError,
|
|
1612
|
+
UserScopedClient,
|
|
1613
|
+
WorkspaceInvitesClient,
|
|
1294
1614
|
authorizeRequest,
|
|
1295
1615
|
authorizeToken,
|
|
1296
1616
|
createAuthorizationErrorResponse,
|
package/package.json
CHANGED