@authyon/server 0.2.0-beta.11 → 0.2.0-beta.14
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 +49 -62
- package/dist/{authorization-CeP_GqT7.d.cts → authorization-B7ynKAud.d.cts} +1 -1
- package/dist/{authorization-D_A6L9Ie.d.ts → authorization-BF015NDJ.d.ts} +1 -1
- package/dist/{authyonServerClient-D-DxoL30.d.cts → authyonServerClient-DmNnjw4z.d.cts} +141 -115
- package/dist/{authyonServerClient-D-DxoL30.d.ts → authyonServerClient-DmNnjw4z.d.ts} +141 -115
- package/dist/bff.cjs +29 -6
- package/dist/bff.d.cts +1 -1
- package/dist/bff.d.ts +1 -1
- package/dist/bff.js +1 -1
- package/dist/{chunk-56H66KLG.js → chunk-TWUVXZOT.js} +29 -6
- package/dist/index.cjs +127 -147
- package/dist/index.d.cts +27 -9
- package/dist/index.d.ts +27 -9
- package/dist/index.js +84 -125
- package/dist/next.d.cts +2 -2
- package/dist/next.d.ts +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
JsonHttpClient,
|
|
8
8
|
LoggingHttpAdapter,
|
|
9
9
|
createSharedTransport
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-TWUVXZOT.js";
|
|
11
11
|
import {
|
|
12
12
|
AuthorizationError,
|
|
13
13
|
AuthyonAbility,
|
|
@@ -102,9 +102,9 @@ function credentialDetail(value) {
|
|
|
102
102
|
accessTokenLifetimeSeconds: value.accessTokenLifetimeSeconds
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
|
-
async function credentialPage(request,
|
|
105
|
+
async function credentialPage(request, path2, options = {}) {
|
|
106
106
|
const query = credentialQuery(options);
|
|
107
|
-
const page = await request(
|
|
107
|
+
const page = await request(path2, { query });
|
|
108
108
|
if (!page || !Array.isArray(page.data))
|
|
109
109
|
throw new TypeError("Authyon: expected a paginated credential response.");
|
|
110
110
|
return {
|
|
@@ -117,13 +117,13 @@ async function credentialPage(request, path, options = {}) {
|
|
|
117
117
|
hasPrev: page.hasPrev
|
|
118
118
|
};
|
|
119
119
|
}
|
|
120
|
-
async function allCredentials(request,
|
|
120
|
+
async function allCredentials(request, path2) {
|
|
121
121
|
const result = [];
|
|
122
122
|
const seen = /* @__PURE__ */ new Set();
|
|
123
123
|
let skip = 0;
|
|
124
124
|
for (let iteration = 0; iteration < 1e3; iteration++) {
|
|
125
125
|
const page = await request(
|
|
126
|
-
|
|
126
|
+
path2,
|
|
127
127
|
iteration === 0 ? {} : { query: { skip, take: 100 } }
|
|
128
128
|
);
|
|
129
129
|
if (Array.isArray(page)) {
|
|
@@ -146,134 +146,67 @@ async function allCredentials(request, path) {
|
|
|
146
146
|
throw new Error("Authyon: use listPage for more than 1000 credential pages.");
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
// ../../internal/core/financial/subjectFinancialAuthorizations.ts
|
|
150
|
+
function path(id, suffix = "") {
|
|
151
|
+
if (typeof id !== "string" || !id.trim())
|
|
152
|
+
throw new TypeError("Authyon: a financial authorization id is required.");
|
|
153
|
+
return `/auth/authorizations/${encodeURIComponent(id)}${suffix}`;
|
|
154
|
+
}
|
|
155
|
+
function subjectFinancialAuthorizations(request) {
|
|
156
|
+
return {
|
|
157
|
+
/** GET /auth/authorizations/{id} — the pending transaction, to show before asking for the code. */
|
|
158
|
+
get: (id) => request(path(id)),
|
|
159
|
+
/** POST /auth/authorizations/{id}/webauthn/options — passkey options for approving this authorization. */
|
|
160
|
+
webauthnOptions: (id) => request(path(id, "/webauthn/options"), { method: "POST" }),
|
|
161
|
+
/**
|
|
162
|
+
* POST /auth/authorizations/{id}/confirm — approves the transaction.
|
|
163
|
+
*
|
|
164
|
+
* Pass the authenticator code or passkey assertion to verify the second
|
|
165
|
+
* factor inline (recommended). Without `input`, the session itself must
|
|
166
|
+
* have used a passkey or authenticator code within the last 5 minutes,
|
|
167
|
+
* otherwise the API answers `step_up_required`.
|
|
168
|
+
*/
|
|
169
|
+
confirm: (id, input) => request(path(id, "/confirm"), { method: "POST", body: input }),
|
|
170
|
+
/** POST /auth/authorizations/{id}/reject — the customer declines the transaction. */
|
|
171
|
+
reject: (id) => request(path(id, "/reject"), { method: "POST" })
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
149
175
|
// src/client/scopedManagementClient.ts
|
|
150
176
|
function scopedRequest(request, source) {
|
|
151
|
-
return async (
|
|
177
|
+
return async (path2, options = {}) => {
|
|
152
178
|
const token = typeof source === "function" ? await source() : source;
|
|
153
179
|
if (typeof token !== "string" || !token.trim() || /\s/u.test(token))
|
|
154
180
|
throw new TypeError("Authyon: a valid access token is required.");
|
|
155
|
-
return request(
|
|
181
|
+
return request(path2, {
|
|
156
182
|
...options,
|
|
157
183
|
headers: { ...options.headers, Authorization: `Bearer ${token}` }
|
|
158
184
|
});
|
|
159
185
|
};
|
|
160
186
|
}
|
|
161
|
-
function environmentPath(scope) {
|
|
162
|
-
return `/platform/workspaces/${segment(scope.workspaceId)}/environments/${segment(scope.environmentId)}`;
|
|
163
|
-
}
|
|
164
|
-
function tenantPath(scope) {
|
|
165
|
-
return `${environmentPath(scope)}/tenants/${segment(scope.tenantId)}`;
|
|
166
|
-
}
|
|
167
|
-
function credentialPath(scope) {
|
|
168
|
-
return `${scope.tenantId === void 0 ? environmentPath(scope) : tenantPath(scope)}/credentials`;
|
|
169
|
-
}
|
|
170
|
-
function workspacePath(id) {
|
|
171
|
-
return `/platform/workspaces/${segment(id)}`;
|
|
172
|
-
}
|
|
173
|
-
function workspaceRole(role) {
|
|
174
|
-
if (role !== "admin" && role !== "auditor")
|
|
175
|
-
throw new TypeError("Authyon: workspace role must be admin or auditor.");
|
|
176
|
-
return role;
|
|
177
|
-
}
|
|
178
187
|
var _request;
|
|
179
|
-
var PlatformScopedClient = class {
|
|
180
|
-
/** @hidden */
|
|
181
|
-
constructor(request, token) {
|
|
182
|
-
__privateAdd(this, _request);
|
|
183
|
-
this.credentials = {
|
|
184
|
-
list: (scope, options = {}) => credentialPage(__privateGet(this, _request), credentialPath(scope), options),
|
|
185
|
-
get: async (scope, credentialId) => credentialDetail(await __privateGet(this, _request).call(this, `${credentialPath(scope)}/${segment(credentialId)}`)),
|
|
186
|
-
create: (scope, input) => __privateGet(this, _request).call(this, credentialPath(scope), {
|
|
187
|
-
method: "POST",
|
|
188
|
-
body: { description: input.description, ...lifetimeBody(input), ...permissionsBody(input) }
|
|
189
|
-
}),
|
|
190
|
-
updatePermissions: (scope, credentialId, input) => __privateGet(this, _request).call(this, `${credentialPath(scope)}/${segment(credentialId)}/permissions`, {
|
|
191
|
-
method: "PUT",
|
|
192
|
-
body: permissionsBody(input)
|
|
193
|
-
}),
|
|
194
|
-
updateScopes: (scope, credentialId, scopes) => this.credentials.updatePermissions(scope, credentialId, { scopes }),
|
|
195
|
-
/** Returns a new secret once. API may require an explicit step-up first. */
|
|
196
|
-
rotate: (scope, credentialId) => __privateGet(this, _request).call(this, `${credentialPath(scope)}/${segment(credentialId)}/rotate`, { method: "POST" }),
|
|
197
|
-
revoke: (scope, credentialId) => __privateGet(this, _request).call(this, `${credentialPath(scope)}/${segment(credentialId)}`, { method: "DELETE" })
|
|
198
|
-
};
|
|
199
|
-
this.workspaces = {
|
|
200
|
-
team: (workspaceId) => __privateGet(this, _request).call(this, `${workspacePath(workspaceId)}/team`),
|
|
201
|
-
members: {
|
|
202
|
-
invite: (workspaceId, input) => __privateGet(this, _request).call(this, `${workspacePath(workspaceId)}/invites`, {
|
|
203
|
-
method: "POST",
|
|
204
|
-
body: { email: input.email, role: workspaceRole(input.role) }
|
|
205
|
-
}),
|
|
206
|
-
/** memberId comes from team.members; it is not the platform userId. */
|
|
207
|
-
remove: (workspaceId, memberId) => __privateGet(this, _request).call(this, `${workspacePath(workspaceId)}/members/${segment(memberId)}`, {
|
|
208
|
-
method: "DELETE"
|
|
209
|
-
}),
|
|
210
|
-
changeRole: (workspaceId, memberId, role) => __privateGet(this, _request).call(this, `${workspacePath(workspaceId)}/members/${segment(memberId)}`, {
|
|
211
|
-
method: "PATCH",
|
|
212
|
-
body: { role: workspaceRole(role) }
|
|
213
|
-
})
|
|
214
|
-
},
|
|
215
|
-
invites: {
|
|
216
|
-
create: (workspaceId, input) => this.workspaces.members.invite(workspaceId, input),
|
|
217
|
-
revoke: (workspaceId, inviteId) => __privateGet(this, _request).call(this, `${workspacePath(workspaceId)}/invites/${segment(inviteId)}`, {
|
|
218
|
-
method: "DELETE"
|
|
219
|
-
})
|
|
220
|
-
}
|
|
221
|
-
};
|
|
222
|
-
this.tenants = {
|
|
223
|
-
members: {
|
|
224
|
-
list: (scope, options = {}) => __privateGet(this, _request).call(this, `${tenantPath(scope)}/members`, { query: options }),
|
|
225
|
-
add: (scope, userId, roles) => __privateGet(this, _request).call(this, `${tenantPath(scope)}/members`, { method: "POST", body: { userId, roles } }),
|
|
226
|
-
remove: (scope, userId) => __privateGet(this, _request).call(this, `${tenantPath(scope)}/members/${segment(userId)}`, { method: "DELETE" })
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
|
-
this.auth = {
|
|
230
|
-
/** Explicitly confirms the current platform session; passwords are not retained. */
|
|
231
|
-
stepUp: (currentPassword) => __privateGet(this, _request).call(this, "/platform/auth/step-up", { method: "POST", body: { currentPassword } })
|
|
232
|
-
};
|
|
233
|
-
__privateSet(this, _request, scopedRequest(request, token));
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
_request = new WeakMap();
|
|
237
|
-
var _request2;
|
|
238
188
|
var UserScopedClient = class {
|
|
239
189
|
/** @hidden */
|
|
240
190
|
constructor(request, token) {
|
|
241
|
-
__privateAdd(this,
|
|
191
|
+
__privateAdd(this, _request);
|
|
242
192
|
this.tenants = {
|
|
243
193
|
members: {
|
|
244
|
-
list: (tenantId, options = {}) => __privateGet(this,
|
|
194
|
+
list: (tenantId, options = {}) => __privateGet(this, _request).call(this, `/auth/tenants/${segment(tenantId)}/members`, { query: options }),
|
|
245
195
|
/** Adds an existing environment user by email; does not send an invitation email. */
|
|
246
|
-
invite: (tenantId, input) => __privateGet(this,
|
|
196
|
+
invite: (tenantId, input) => __privateGet(this, _request).call(this, `/auth/tenants/${segment(tenantId)}/members`, {
|
|
247
197
|
method: "POST",
|
|
248
198
|
body: { email: input.email, roles: input.roles }
|
|
249
199
|
}),
|
|
250
|
-
remove: (tenantId, userId) => __privateGet(this,
|
|
200
|
+
remove: (tenantId, userId) => __privateGet(this, _request).call(this, `/auth/tenants/${segment(tenantId)}/members/${segment(userId)}`, {
|
|
251
201
|
method: "DELETE"
|
|
252
202
|
})
|
|
253
203
|
}
|
|
254
204
|
};
|
|
255
|
-
__privateSet(this,
|
|
256
|
-
|
|
257
|
-
};
|
|
258
|
-
_request2 = new WeakMap();
|
|
259
|
-
var _request3;
|
|
260
|
-
var WorkspaceInvitesClient = class {
|
|
261
|
-
/** @hidden */
|
|
262
|
-
constructor(request) {
|
|
263
|
-
__privateAdd(this, _request3);
|
|
264
|
-
__privateSet(this, _request3, request);
|
|
265
|
-
}
|
|
266
|
-
preview(token) {
|
|
267
|
-
return __privateGet(this, _request3).call(this, `/platform/workspace-invites/${segment(token)}`);
|
|
268
|
-
}
|
|
269
|
-
accept(token, input = {}) {
|
|
270
|
-
return __privateGet(this, _request3).call(this, `/platform/workspace-invites/${segment(token)}/accept`, {
|
|
271
|
-
method: "POST",
|
|
272
|
-
body: { name: input.name, password: input.password }
|
|
273
|
-
});
|
|
205
|
+
__privateSet(this, _request, scopedRequest(request, token));
|
|
206
|
+
this.financialAuthorizations = subjectFinancialAuthorizations(__privateGet(this, _request));
|
|
274
207
|
}
|
|
275
208
|
};
|
|
276
|
-
|
|
209
|
+
_request = new WeakMap();
|
|
277
210
|
|
|
278
211
|
// ../../internal/core/auth/expiringTokenProvider.ts
|
|
279
212
|
var _token, _inFlight;
|
|
@@ -352,9 +285,6 @@ var AuthyonServerClient = class {
|
|
|
352
285
|
}
|
|
353
286
|
})
|
|
354
287
|
};
|
|
355
|
-
this.workspaceInvites = new WorkspaceInvitesClient(
|
|
356
|
-
(path, options) => this.http.request(path, options)
|
|
357
|
-
);
|
|
358
288
|
// ── Environment management (users, tenants, roles, permissions, audit) ───
|
|
359
289
|
this.environment = {
|
|
360
290
|
users: {
|
|
@@ -449,12 +379,12 @@ var AuthyonServerClient = class {
|
|
|
449
379
|
credentials: {
|
|
450
380
|
/** GET /env/tenants/{tenantId}/credentials. Returns metadata only, including revoked credentials. */
|
|
451
381
|
list: (tenantId) => allCredentials(
|
|
452
|
-
(
|
|
382
|
+
(path2, options) => this.request(path2, { ...options, envBearer: true }),
|
|
453
383
|
`/env/tenants/${segment(tenantId)}/credentials`
|
|
454
384
|
),
|
|
455
385
|
/** Paginated searchable listing. Prefer this over loading every credential. */
|
|
456
386
|
listPage: (tenantId, options = {}) => credentialPage(
|
|
457
|
-
(
|
|
387
|
+
(path2, requestOptions) => this.request(path2, { ...requestOptions, envBearer: true }),
|
|
458
388
|
`/env/tenants/${segment(tenantId)}/credentials`,
|
|
459
389
|
options
|
|
460
390
|
),
|
|
@@ -625,6 +555,41 @@ var AuthyonServerClient = class {
|
|
|
625
555
|
/** GET /permissions/reserved — reserved permission names you can't redefine. */
|
|
626
556
|
reserved: () => this.request("/permissions/reserved", { envBearer: true })
|
|
627
557
|
},
|
|
558
|
+
/**
|
|
559
|
+
* Transaction-bound step-up for financial operations. The environment
|
|
560
|
+
* credential needs the `authyon:financial:authorize` scope.
|
|
561
|
+
*
|
|
562
|
+
* 1. `create()` the authorization for the transaction and the customer.
|
|
563
|
+
* 2. The customer approves it with their authenticator code or passkey
|
|
564
|
+
* (`@authyon/auth` → `financialAuthorizations.confirm`).
|
|
565
|
+
* 3. `consume()` it with the same transaction right before executing it.
|
|
566
|
+
*/
|
|
567
|
+
financialAuthorizations: {
|
|
568
|
+
/** POST /env/authorizations — registers a transaction awaiting the customer's approval. */
|
|
569
|
+
create: (input) => {
|
|
570
|
+
const { idempotencyKey, ...body } = input;
|
|
571
|
+
if (typeof idempotencyKey !== "string" || !idempotencyKey.trim())
|
|
572
|
+
throw new TypeError("Authyon: `idempotencyKey` is required.");
|
|
573
|
+
return this.request("/env/authorizations", {
|
|
574
|
+
method: "POST",
|
|
575
|
+
envBearer: true,
|
|
576
|
+
headers: { "Idempotency-Key": idempotencyKey },
|
|
577
|
+
body
|
|
578
|
+
});
|
|
579
|
+
},
|
|
580
|
+
/** GET /env/authorizations/{id} — current status and, once approved, the assurance evidence. */
|
|
581
|
+
get: (id) => this.request(`/env/authorizations/${segment(id)}`, { envBearer: true }),
|
|
582
|
+
/**
|
|
583
|
+
* POST /env/authorizations/{id}/consume — redeems an approved
|
|
584
|
+
* authorization exactly once. Resend the same transaction given to
|
|
585
|
+
* `create()`; any difference fails with `transaction_mismatch`.
|
|
586
|
+
*/
|
|
587
|
+
consume: (id, transaction) => this.request(`/env/authorizations/${segment(id)}/consume`, {
|
|
588
|
+
method: "POST",
|
|
589
|
+
envBearer: true,
|
|
590
|
+
body: transaction
|
|
591
|
+
})
|
|
592
|
+
},
|
|
628
593
|
audit: {
|
|
629
594
|
/** GET /env/audit — paginated list of the environment's audit events. */
|
|
630
595
|
list: (params = {}) => this.request("/env/audit", { envBearer: true, query: params }),
|
|
@@ -675,7 +640,7 @@ var AuthyonServerClient = class {
|
|
|
675
640
|
};
|
|
676
641
|
});
|
|
677
642
|
}
|
|
678
|
-
async request(
|
|
643
|
+
async request(path2, options = {}) {
|
|
679
644
|
const headers = {
|
|
680
645
|
...clientIpHeaders({ clientIp: this.clientIp }),
|
|
681
646
|
...options.headers
|
|
@@ -684,7 +649,7 @@ var AuthyonServerClient = class {
|
|
|
684
649
|
headers.Authorization = `Bearer ${await this.getEnvironmentAccessToken()}`;
|
|
685
650
|
}
|
|
686
651
|
if (this.envKey) headers["X-Authyon-Environment"] = this.envKey;
|
|
687
|
-
return this.http.request(
|
|
652
|
+
return this.http.request(path2, { ...options, headers });
|
|
688
653
|
}
|
|
689
654
|
/** Mints (and caches) an environment access token from `clientId`/`clientSecret`. */
|
|
690
655
|
async getEnvironmentAccessToken() {
|
|
@@ -739,17 +704,13 @@ var AuthyonServerClient = class {
|
|
|
739
704
|
tenant(credentials) {
|
|
740
705
|
return new TenantScopedClient(this, credentials);
|
|
741
706
|
}
|
|
742
|
-
/** Uses only the supplied platform-user access token. */
|
|
743
|
-
platform(token) {
|
|
744
|
-
return new PlatformScopedClient((path, options) => this.http.request(path, options), token);
|
|
745
|
-
}
|
|
746
707
|
/** Uses an end-user token; the configured environment key selects the environment. */
|
|
747
708
|
user(token) {
|
|
748
|
-
return new UserScopedClient((
|
|
709
|
+
return new UserScopedClient((path2, options) => this.request(path2, options), token);
|
|
749
710
|
}
|
|
750
711
|
/** @internal used by {@link TenantScopedClient} to share the base URL/fetch/error handling. */
|
|
751
|
-
_requestAsTenant(accessToken,
|
|
752
|
-
return this.request(
|
|
712
|
+
_requestAsTenant(accessToken, path2, options = {}) {
|
|
713
|
+
return this.request(path2, {
|
|
753
714
|
...options,
|
|
754
715
|
headers: { ...options.headers, Authorization: `Bearer ${accessToken}` },
|
|
755
716
|
envBearer: false
|
|
@@ -826,8 +787,8 @@ var TenantScopedClient = class {
|
|
|
826
787
|
async getAccessToken() {
|
|
827
788
|
return this.tokenProvider.getAccessToken();
|
|
828
789
|
}
|
|
829
|
-
async request(
|
|
830
|
-
return this.server._requestAsTenant(await this.getAccessToken(),
|
|
790
|
+
async request(path2, options = {}) {
|
|
791
|
+
return this.server._requestAsTenant(await this.getAccessToken(), path2, options);
|
|
831
792
|
}
|
|
832
793
|
/** POST /tenant/auth/validate — validates this tenant client's current bearer token. */
|
|
833
794
|
async validate(context) {
|
|
@@ -890,11 +851,9 @@ export {
|
|
|
890
851
|
FetchHttpAdapter,
|
|
891
852
|
JwksTokenVerifier,
|
|
892
853
|
LoggingHttpAdapter,
|
|
893
|
-
PlatformScopedClient,
|
|
894
854
|
TenantScopedClient,
|
|
895
855
|
TokenVerificationError,
|
|
896
856
|
UserScopedClient,
|
|
897
|
-
WorkspaceInvitesClient,
|
|
898
857
|
authorizeRequest,
|
|
899
858
|
authorizeToken,
|
|
900
859
|
createAuthorizationErrorResponse,
|
package/dist/next.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import { R as RequestAuthorizationOptions, A as AbilitySubject, a as AuthorizationError } from './authorization-
|
|
3
|
-
import { A as AuthyonServerClient } from './authyonServerClient-
|
|
2
|
+
import { R as RequestAuthorizationOptions, A as AbilitySubject, a as AuthorizationError } from './authorization-B7ynKAud.cjs';
|
|
3
|
+
import { A as AuthyonServerClient } from './authyonServerClient-DmNnjw4z.cjs';
|
|
4
4
|
import 'jose';
|
|
5
5
|
|
|
6
6
|
interface ServerPermissionGuardFallbackContext {
|
package/dist/next.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import { R as RequestAuthorizationOptions, A as AbilitySubject, a as AuthorizationError } from './authorization-
|
|
3
|
-
import { A as AuthyonServerClient } from './authyonServerClient-
|
|
2
|
+
import { R as RequestAuthorizationOptions, A as AbilitySubject, a as AuthorizationError } from './authorization-BF015NDJ.js';
|
|
3
|
+
import { A as AuthyonServerClient } from './authyonServerClient-DmNnjw4z.js';
|
|
4
4
|
import 'jose';
|
|
5
5
|
|
|
6
6
|
interface ServerPermissionGuardFallbackContext {
|
package/package.json
CHANGED