@authyon/server 0.2.0-beta.15 → 0.2.0-beta.17
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 -2
- package/dist/{authorization-WlwcTBwG.d.ts → authorization-BvjIWPcU.d.ts} +1 -1
- package/dist/{authorization-B82XXf3B.d.cts → authorization-C0Mg5gUv.d.cts} +1 -1
- package/dist/{authyonServerClient-DQzhfaja.d.cts → authyonServerClient-1_1qNRDa.d.cts} +249 -58
- package/dist/{authyonServerClient-DQzhfaja.d.ts → authyonServerClient-1_1qNRDa.d.ts} +249 -58
- package/dist/bff.cjs +18 -0
- package/dist/bff.d.cts +8 -1
- package/dist/bff.d.ts +8 -1
- package/dist/bff.js +18 -1
- package/dist/{chunk-WPPEV5BA.js → chunk-TDJNBD3Z.js} +1 -0
- package/dist/index.cjs +122 -3
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +122 -4
- package/dist/next.d.cts +2 -2
- package/dist/next.d.ts +2 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -174,8 +174,22 @@ function path(id, suffix = "") {
|
|
|
174
174
|
throw new TypeError("Authyon: an approval id is required.");
|
|
175
175
|
return `/auth/authorizations/${encodeURIComponent(id)}${suffix}`;
|
|
176
176
|
}
|
|
177
|
+
var NO_METHODS = {
|
|
178
|
+
password: false,
|
|
179
|
+
authenticator: false,
|
|
180
|
+
emailCode: false,
|
|
181
|
+
passkey: false,
|
|
182
|
+
passkeyCount: 0,
|
|
183
|
+
recoveryCodes: 0,
|
|
184
|
+
sso: [],
|
|
185
|
+
twoFactor: false
|
|
186
|
+
};
|
|
177
187
|
function subjectSecurity(request) {
|
|
178
188
|
return {
|
|
189
|
+
methods: async () => {
|
|
190
|
+
const me = await request("/auth/me");
|
|
191
|
+
return me.security ?? NO_METHODS;
|
|
192
|
+
},
|
|
179
193
|
approvals: {
|
|
180
194
|
get: (id) => request(path(id)),
|
|
181
195
|
webauthnOptions: (id) => request(path(id, "/webauthn/options"), { method: "POST" }),
|
|
@@ -213,6 +227,31 @@ var UserScopedClient = class {
|
|
|
213
227
|
remove: (tenantId, userId) => __privateGet(this, _request).call(this, `/auth/tenants/${segment(tenantId)}/members/${segment(userId)}`, {
|
|
214
228
|
method: "DELETE"
|
|
215
229
|
})
|
|
230
|
+
},
|
|
231
|
+
/**
|
|
232
|
+
* Invites by e-mail or by link, acting as the user. Requires the
|
|
233
|
+
* `tenants:members:invite` permission on the tenant.
|
|
234
|
+
*/
|
|
235
|
+
invites: {
|
|
236
|
+
list: (tenantId) => __privateGet(this, _request).call(this, `/auth/tenants/${segment(tenantId)}/invites`),
|
|
237
|
+
/** Always returns `acceptUrl`; `sendEmail: false` skips the e-mail. */
|
|
238
|
+
create: (tenantId, input) => __privateGet(this, _request).call(this, `/auth/tenants/${segment(tenantId)}/invites`, {
|
|
239
|
+
method: "POST",
|
|
240
|
+
body: {
|
|
241
|
+
email: input.email,
|
|
242
|
+
roles: input.roles,
|
|
243
|
+
sendEmail: input.sendEmail ?? true,
|
|
244
|
+
redirectUri: input.redirectUri
|
|
245
|
+
}
|
|
246
|
+
}),
|
|
247
|
+
/** New link (the previous one stops working), mailed unless `sendEmail` is `false`. */
|
|
248
|
+
resend: (tenantId, inviteId, input = {}) => __privateGet(this, _request).call(this, `/auth/tenants/${segment(tenantId)}/invites/${segment(inviteId)}/resend`, {
|
|
249
|
+
method: "POST",
|
|
250
|
+
body: { sendEmail: input.sendEmail ?? true }
|
|
251
|
+
}),
|
|
252
|
+
revoke: (tenantId, inviteId) => __privateGet(this, _request).call(this, `/auth/tenants/${segment(tenantId)}/invites/${segment(inviteId)}`, {
|
|
253
|
+
method: "DELETE"
|
|
254
|
+
})
|
|
216
255
|
}
|
|
217
256
|
};
|
|
218
257
|
__privateSet(this, _request, scopedRequest(request, token));
|
|
@@ -279,6 +318,7 @@ var ErrorCodes = {
|
|
|
279
318
|
UserNotFound: "user_not_found",
|
|
280
319
|
TemporarilyUnavailable: "temporarily_unavailable",
|
|
281
320
|
InsufficientScope: "insufficient_scope",
|
|
321
|
+
CredentialThrottled: "credential_throttled",
|
|
282
322
|
ApprovalNotFound: "authorization_not_found",
|
|
283
323
|
SessionRevoked: "session_revoked",
|
|
284
324
|
TwoFactorTooManyFailures: "user.2fa.too_many_failures"
|
|
@@ -1006,6 +1046,61 @@ var AuthyonServerClient = class {
|
|
|
1006
1046
|
{ method: "DELETE", envBearer: true }
|
|
1007
1047
|
)
|
|
1008
1048
|
},
|
|
1049
|
+
/**
|
|
1050
|
+
* Invites by e-mail or by link — for addresses that may not have an
|
|
1051
|
+
* account yet; accepting creates it. Managing them needs the
|
|
1052
|
+
* credential's `authyon:users:write` scope (listing, `authyon:tenants:read`).
|
|
1053
|
+
*/
|
|
1054
|
+
invites: {
|
|
1055
|
+
/** GET /env/tenants/{tenantId}/invites — every invite with its status, newest first. */
|
|
1056
|
+
list: (tenantId) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}/invites`, { envBearer: true }),
|
|
1057
|
+
/**
|
|
1058
|
+
* POST /env/tenants/{tenantId}/invites — invite an address. Always
|
|
1059
|
+
* returns `acceptUrl`; with `sendEmail: false` Authyon does not mail
|
|
1060
|
+
* it and you deliver the link yourself. Valid 7 days, single use, and
|
|
1061
|
+
* not readable again later.
|
|
1062
|
+
*/
|
|
1063
|
+
create: (tenantId, input) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}/invites`, {
|
|
1064
|
+
method: "POST",
|
|
1065
|
+
envBearer: true,
|
|
1066
|
+
body: {
|
|
1067
|
+
email: input.email,
|
|
1068
|
+
roles: input.roles,
|
|
1069
|
+
sendEmail: input.sendEmail ?? true,
|
|
1070
|
+
redirectUri: input.redirectUri
|
|
1071
|
+
}
|
|
1072
|
+
}),
|
|
1073
|
+
/** POST .../invites/{inviteId}/resend — new link (the previous one stops working), mailed unless `sendEmail` is `false`. */
|
|
1074
|
+
resend: (tenantId, inviteId, input = {}) => this.request(
|
|
1075
|
+
`/env/tenants/${encodeURIComponent(tenantId)}/invites/${encodeURIComponent(inviteId)}/resend`,
|
|
1076
|
+
{ method: "POST", envBearer: true, body: { sendEmail: input.sendEmail ?? true } }
|
|
1077
|
+
),
|
|
1078
|
+
/** DELETE /env/tenants/{tenantId}/invites/{inviteId} — revoke a pending invite. */
|
|
1079
|
+
revoke: (tenantId, inviteId) => this.request(
|
|
1080
|
+
`/env/tenants/${encodeURIComponent(tenantId)}/invites/${encodeURIComponent(inviteId)}`,
|
|
1081
|
+
{ method: "DELETE", envBearer: true }
|
|
1082
|
+
),
|
|
1083
|
+
/**
|
|
1084
|
+
* POST /auth/tenant-invites/preview — for a backend hosting the accept
|
|
1085
|
+
* page. Public: needs only `envKey`, the token is the credential.
|
|
1086
|
+
*/
|
|
1087
|
+
preview: (token) => this.request("/auth/tenant-invites/preview", { method: "POST", body: { token } }),
|
|
1088
|
+
/**
|
|
1089
|
+
* Joins the tenant; for an address with no account, also creates it
|
|
1090
|
+
* (password required) with the e-mail already confirmed. Does not
|
|
1091
|
+
* sign the user in.
|
|
1092
|
+
*
|
|
1093
|
+
* Without metadata: POST /auth/tenant-invites/accept — public, needs
|
|
1094
|
+
* only `envKey`. With `publicMetadata`/`privateMetadata`: POST
|
|
1095
|
+
* /env/tenant-invites/accept with the environment credential
|
|
1096
|
+
* (`authyon:users:write`), since only your backend may set them.
|
|
1097
|
+
*/
|
|
1098
|
+
accept: (input) => input.publicMetadata !== void 0 || input.privateMetadata !== void 0 ? this.request("/env/tenant-invites/accept", {
|
|
1099
|
+
method: "POST",
|
|
1100
|
+
envBearer: true,
|
|
1101
|
+
body: input
|
|
1102
|
+
}) : this.request("/auth/tenant-invites/accept", { method: "POST", body: input })
|
|
1103
|
+
},
|
|
1009
1104
|
roles: {
|
|
1010
1105
|
/** GET /env/tenants/{tenantId}/roles — list a tenant's roles. */
|
|
1011
1106
|
list: (tenantId) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}/roles`, { envBearer: true }),
|
|
@@ -1077,8 +1172,9 @@ var AuthyonServerClient = class {
|
|
|
1077
1172
|
};
|
|
1078
1173
|
// ── Security: one-time codes and approvals ───────────────────────────────
|
|
1079
1174
|
//
|
|
1080
|
-
// Everything here runs with the environment credential
|
|
1081
|
-
// `authyon:
|
|
1175
|
+
// Everything here runs with the environment credential: `otp` needs the
|
|
1176
|
+
// `authyon:otp:verify` scope, `approvals` needs `authyon:financial:authorize`.
|
|
1177
|
+
// Keep those credentials on the server.
|
|
1082
1178
|
this.security = {
|
|
1083
1179
|
otp: {
|
|
1084
1180
|
/**
|
|
@@ -1086,7 +1182,8 @@ var AuthyonServerClient = class {
|
|
|
1086
1182
|
* app (TOTP) code. A wrong code returns `{ valid: false }` instead of
|
|
1087
1183
|
* throwing. Each code is accepted once; 3 wrong codes in a row sign the
|
|
1088
1184
|
* user out everywhere (`sessionsRevoked: true`); 5 lock the check for 15
|
|
1089
|
-
* minutes (`rate_limited`).
|
|
1185
|
+
* minutes (`rate_limited`). More than 50 wrong codes in 10 minutes from the
|
|
1186
|
+
* same credential pause it (`credential_throttled`). Needs `authyon:otp:verify`.
|
|
1090
1187
|
*/
|
|
1091
1188
|
check: (userId, code) => this.request(`/env/users/${segment(userId)}/otp/verify`, {
|
|
1092
1189
|
method: "POST",
|
|
@@ -1250,6 +1347,28 @@ var AuthyonServerClient = class {
|
|
|
1250
1347
|
_clientSecret = new WeakMap();
|
|
1251
1348
|
var TenantScopedClient = class {
|
|
1252
1349
|
constructor(server, credentials) {
|
|
1350
|
+
/** Invites to the token's tenant, by e-mail or by link. */
|
|
1351
|
+
this.invites = {
|
|
1352
|
+
/** GET /tenant/invites — every invite with its status, newest first. */
|
|
1353
|
+
list: () => this.request("/tenant/invites"),
|
|
1354
|
+
/** POST /tenant/invites — always returns `acceptUrl`; `sendEmail: false` skips the e-mail. */
|
|
1355
|
+
create: (input) => this.request("/tenant/invites", {
|
|
1356
|
+
method: "POST",
|
|
1357
|
+
body: {
|
|
1358
|
+
email: input.email,
|
|
1359
|
+
roles: input.roles,
|
|
1360
|
+
sendEmail: input.sendEmail ?? true,
|
|
1361
|
+
redirectUri: input.redirectUri
|
|
1362
|
+
}
|
|
1363
|
+
}),
|
|
1364
|
+
/** POST /tenant/invites/{inviteId}/resend — new link (the previous one stops working), mailed unless `sendEmail` is `false`. */
|
|
1365
|
+
resend: (inviteId, input = {}) => this.request(`/tenant/invites/${encodeURIComponent(inviteId)}/resend`, {
|
|
1366
|
+
method: "POST",
|
|
1367
|
+
body: { sendEmail: input.sendEmail ?? true }
|
|
1368
|
+
}),
|
|
1369
|
+
/** DELETE /tenant/invites/{inviteId} — revoke a pending invite. */
|
|
1370
|
+
revoke: (inviteId) => this.request(`/tenant/invites/${encodeURIComponent(inviteId)}`, { method: "DELETE" })
|
|
1371
|
+
};
|
|
1253
1372
|
this.members = {
|
|
1254
1373
|
/**
|
|
1255
1374
|
* GET /tenant/members — members of the token's tenant.
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-
|
|
2
|
-
export { b as
|
|
3
|
-
export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRequirement, f as AbilityRule, A as AbilitySubject, g as AuthorizationContext, a as AuthorizationError, h as AuthorizationOptions, i as AuthyonAbility, j as AuthyonAbilityBuilder, k as AuthyonAbilityOptions, l as AuthyonPermissionSource, E as ExpressAuthorizationMiddlewareOptions, m as ExpressNext, n as ExpressRequestLike, o as ExpressResponseLike, P as PermissionGroup, R as RequestAuthorizationOptions, p as authorizeRequest, q as authorizeToken, r as createAuthorizationErrorResponse, s as createAuthyonAbility, t as createAuthyonRules, u as createExpressAuthorizationMiddleware, v as hasPermission, w as hasPermissionGroup } from './authorization-
|
|
1
|
+
import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-1_1qNRDa.cjs';
|
|
2
|
+
export { b as AcceptTenantInviteInput, c as AccessTokenSource, d as Approval, e as ApprovalAssurance, f as ApprovalPayload, g as ApprovalStatus, h as ApprovalWebAuthnOptions, i as AuditEvent, j as AuthyonJwksDiscoveryOptions, k as AuthyonJwtClaims, l as AuthyonServerClientOptions, C as ClientCredentials, m as ClientRequestContext, n as ConfirmApprovalInput, o as ConsumedApproval, p as CreateApprovalInput, q as CreateCredentialInput, r as CreateOrganizationInput, s as CreatePermissionInput, t as CreateTenantCredentialInput, u as CreateUserInput, v as CredentialCreator, w as CredentialDetail, x as CredentialListOptions, y as CredentialPermissionsInput, E as EnvironmentUser, F as FetchHttpAdapter, z as HttpAdapterRequest, B as HttpLogEvent, D as HttpLogger, I as IntrospectResult, G as InviteTenantMemberInput, J as JsonWebKeySet, K as JwksTokenVerifier, L as JwksTokenVerifierOptions, M as LoggingHttpAdapter, N as LoginActivity, O as OpenIdConfiguration, P as Organization, Q as OtpCheckResult, R as Paged, S as PaginationOptions, T as Permission, U as PermissionsByRole, V as ReservedPermissions, W as Role, X as RoleGrant, Y as RoleInput, Z as RoleList, _ as RolePermissions, $ as SafeJwtAlgorithm, a0 as SecurityMethods, a1 as SubjectApprovals, a2 as SubjectSecurity, a3 as TenantClientValidationResult, a4 as TenantCredentialIssued, a5 as TenantCredentialSummary, a6 as TenantInvite, a7 as TenantInviteAccepted, a8 as TenantInviteInput, a9 as TenantInviteIssued, aa as TenantInvitePreview, ab as TenantInviteStatus, ac as TenantMember, ad as TenantMemberPage, ae as TenantMembership, af as TenantScopedClient, ag as TokenResult, ah as TokenVerificationError, ai as TokenVerificationErrorCode, aj as UpdateOrganizationInput, ak as User, al as UserScopedClient, am as ValidateResult, an as VerifiedAccessToken, ao as createClient, ap as normalizeClientIp } from './authyonServerClient-1_1qNRDa.cjs';
|
|
3
|
+
export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRequirement, f as AbilityRule, A as AbilitySubject, g as AuthorizationContext, a as AuthorizationError, h as AuthorizationOptions, i as AuthyonAbility, j as AuthyonAbilityBuilder, k as AuthyonAbilityOptions, l as AuthyonPermissionSource, E as ExpressAuthorizationMiddlewareOptions, m as ExpressNext, n as ExpressRequestLike, o as ExpressResponseLike, P as PermissionGroup, R as RequestAuthorizationOptions, p as authorizeRequest, q as authorizeToken, r as createAuthorizationErrorResponse, s as createAuthyonAbility, t as createAuthyonRules, u as createExpressAuthorizationMiddleware, v as hasPermission, w as hasPermissionGroup } from './authorization-C0Mg5gUv.cjs';
|
|
4
4
|
import 'jose';
|
|
5
5
|
|
|
6
6
|
declare const ErrorCodes: {
|
|
@@ -27,6 +27,7 @@ declare const ErrorCodes: {
|
|
|
27
27
|
readonly UserNotFound: "user_not_found";
|
|
28
28
|
readonly TemporarilyUnavailable: "temporarily_unavailable";
|
|
29
29
|
readonly InsufficientScope: "insufficient_scope";
|
|
30
|
+
readonly CredentialThrottled: "credential_throttled";
|
|
30
31
|
readonly ApprovalNotFound: "authorization_not_found";
|
|
31
32
|
readonly SessionRevoked: "session_revoked";
|
|
32
33
|
readonly TwoFactorTooManyFailures: "user.2fa.too_many_failures";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-
|
|
2
|
-
export { b as
|
|
3
|
-
export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRequirement, f as AbilityRule, A as AbilitySubject, g as AuthorizationContext, a as AuthorizationError, h as AuthorizationOptions, i as AuthyonAbility, j as AuthyonAbilityBuilder, k as AuthyonAbilityOptions, l as AuthyonPermissionSource, E as ExpressAuthorizationMiddlewareOptions, m as ExpressNext, n as ExpressRequestLike, o as ExpressResponseLike, P as PermissionGroup, R as RequestAuthorizationOptions, p as authorizeRequest, q as authorizeToken, r as createAuthorizationErrorResponse, s as createAuthyonAbility, t as createAuthyonRules, u as createExpressAuthorizationMiddleware, v as hasPermission, w as hasPermissionGroup } from './authorization-
|
|
1
|
+
import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-1_1qNRDa.js';
|
|
2
|
+
export { b as AcceptTenantInviteInput, c as AccessTokenSource, d as Approval, e as ApprovalAssurance, f as ApprovalPayload, g as ApprovalStatus, h as ApprovalWebAuthnOptions, i as AuditEvent, j as AuthyonJwksDiscoveryOptions, k as AuthyonJwtClaims, l as AuthyonServerClientOptions, C as ClientCredentials, m as ClientRequestContext, n as ConfirmApprovalInput, o as ConsumedApproval, p as CreateApprovalInput, q as CreateCredentialInput, r as CreateOrganizationInput, s as CreatePermissionInput, t as CreateTenantCredentialInput, u as CreateUserInput, v as CredentialCreator, w as CredentialDetail, x as CredentialListOptions, y as CredentialPermissionsInput, E as EnvironmentUser, F as FetchHttpAdapter, z as HttpAdapterRequest, B as HttpLogEvent, D as HttpLogger, I as IntrospectResult, G as InviteTenantMemberInput, J as JsonWebKeySet, K as JwksTokenVerifier, L as JwksTokenVerifierOptions, M as LoggingHttpAdapter, N as LoginActivity, O as OpenIdConfiguration, P as Organization, Q as OtpCheckResult, R as Paged, S as PaginationOptions, T as Permission, U as PermissionsByRole, V as ReservedPermissions, W as Role, X as RoleGrant, Y as RoleInput, Z as RoleList, _ as RolePermissions, $ as SafeJwtAlgorithm, a0 as SecurityMethods, a1 as SubjectApprovals, a2 as SubjectSecurity, a3 as TenantClientValidationResult, a4 as TenantCredentialIssued, a5 as TenantCredentialSummary, a6 as TenantInvite, a7 as TenantInviteAccepted, a8 as TenantInviteInput, a9 as TenantInviteIssued, aa as TenantInvitePreview, ab as TenantInviteStatus, ac as TenantMember, ad as TenantMemberPage, ae as TenantMembership, af as TenantScopedClient, ag as TokenResult, ah as TokenVerificationError, ai as TokenVerificationErrorCode, aj as UpdateOrganizationInput, ak as User, al as UserScopedClient, am as ValidateResult, an as VerifiedAccessToken, ao as createClient, ap as normalizeClientIp } from './authyonServerClient-1_1qNRDa.js';
|
|
3
|
+
export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRequirement, f as AbilityRule, A as AbilitySubject, g as AuthorizationContext, a as AuthorizationError, h as AuthorizationOptions, i as AuthyonAbility, j as AuthyonAbilityBuilder, k as AuthyonAbilityOptions, l as AuthyonPermissionSource, E as ExpressAuthorizationMiddlewareOptions, m as ExpressNext, n as ExpressRequestLike, o as ExpressResponseLike, P as PermissionGroup, R as RequestAuthorizationOptions, p as authorizeRequest, q as authorizeToken, r as createAuthorizationErrorResponse, s as createAuthyonAbility, t as createAuthyonRules, u as createExpressAuthorizationMiddleware, v as hasPermission, w as hasPermissionGroup } from './authorization-BvjIWPcU.js';
|
|
4
4
|
import 'jose';
|
|
5
5
|
|
|
6
6
|
declare const ErrorCodes: {
|
|
@@ -27,6 +27,7 @@ declare const ErrorCodes: {
|
|
|
27
27
|
readonly UserNotFound: "user_not_found";
|
|
28
28
|
readonly TemporarilyUnavailable: "temporarily_unavailable";
|
|
29
29
|
readonly InsufficientScope: "insufficient_scope";
|
|
30
|
+
readonly CredentialThrottled: "credential_throttled";
|
|
30
31
|
readonly ApprovalNotFound: "authorization_not_found";
|
|
31
32
|
readonly SessionRevoked: "session_revoked";
|
|
32
33
|
readonly TwoFactorTooManyFailures: "user.2fa.too_many_failures";
|
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-TDJNBD3Z.js";
|
|
11
11
|
import {
|
|
12
12
|
AuthorizationError,
|
|
13
13
|
AuthyonAbility,
|
|
@@ -152,8 +152,22 @@ function path(id, suffix = "") {
|
|
|
152
152
|
throw new TypeError("Authyon: an approval id is required.");
|
|
153
153
|
return `/auth/authorizations/${encodeURIComponent(id)}${suffix}`;
|
|
154
154
|
}
|
|
155
|
+
var NO_METHODS = {
|
|
156
|
+
password: false,
|
|
157
|
+
authenticator: false,
|
|
158
|
+
emailCode: false,
|
|
159
|
+
passkey: false,
|
|
160
|
+
passkeyCount: 0,
|
|
161
|
+
recoveryCodes: 0,
|
|
162
|
+
sso: [],
|
|
163
|
+
twoFactor: false
|
|
164
|
+
};
|
|
155
165
|
function subjectSecurity(request) {
|
|
156
166
|
return {
|
|
167
|
+
methods: async () => {
|
|
168
|
+
const me = await request("/auth/me");
|
|
169
|
+
return me.security ?? NO_METHODS;
|
|
170
|
+
},
|
|
157
171
|
approvals: {
|
|
158
172
|
get: (id) => request(path(id)),
|
|
159
173
|
webauthnOptions: (id) => request(path(id, "/webauthn/options"), { method: "POST" }),
|
|
@@ -191,6 +205,31 @@ var UserScopedClient = class {
|
|
|
191
205
|
remove: (tenantId, userId) => __privateGet(this, _request).call(this, `/auth/tenants/${segment(tenantId)}/members/${segment(userId)}`, {
|
|
192
206
|
method: "DELETE"
|
|
193
207
|
})
|
|
208
|
+
},
|
|
209
|
+
/**
|
|
210
|
+
* Invites by e-mail or by link, acting as the user. Requires the
|
|
211
|
+
* `tenants:members:invite` permission on the tenant.
|
|
212
|
+
*/
|
|
213
|
+
invites: {
|
|
214
|
+
list: (tenantId) => __privateGet(this, _request).call(this, `/auth/tenants/${segment(tenantId)}/invites`),
|
|
215
|
+
/** Always returns `acceptUrl`; `sendEmail: false` skips the e-mail. */
|
|
216
|
+
create: (tenantId, input) => __privateGet(this, _request).call(this, `/auth/tenants/${segment(tenantId)}/invites`, {
|
|
217
|
+
method: "POST",
|
|
218
|
+
body: {
|
|
219
|
+
email: input.email,
|
|
220
|
+
roles: input.roles,
|
|
221
|
+
sendEmail: input.sendEmail ?? true,
|
|
222
|
+
redirectUri: input.redirectUri
|
|
223
|
+
}
|
|
224
|
+
}),
|
|
225
|
+
/** New link (the previous one stops working), mailed unless `sendEmail` is `false`. */
|
|
226
|
+
resend: (tenantId, inviteId, input = {}) => __privateGet(this, _request).call(this, `/auth/tenants/${segment(tenantId)}/invites/${segment(inviteId)}/resend`, {
|
|
227
|
+
method: "POST",
|
|
228
|
+
body: { sendEmail: input.sendEmail ?? true }
|
|
229
|
+
}),
|
|
230
|
+
revoke: (tenantId, inviteId) => __privateGet(this, _request).call(this, `/auth/tenants/${segment(tenantId)}/invites/${segment(inviteId)}`, {
|
|
231
|
+
method: "DELETE"
|
|
232
|
+
})
|
|
194
233
|
}
|
|
195
234
|
};
|
|
196
235
|
__privateSet(this, _request, scopedRequest(request, token));
|
|
@@ -484,6 +523,61 @@ var AuthyonServerClient = class {
|
|
|
484
523
|
{ method: "DELETE", envBearer: true }
|
|
485
524
|
)
|
|
486
525
|
},
|
|
526
|
+
/**
|
|
527
|
+
* Invites by e-mail or by link — for addresses that may not have an
|
|
528
|
+
* account yet; accepting creates it. Managing them needs the
|
|
529
|
+
* credential's `authyon:users:write` scope (listing, `authyon:tenants:read`).
|
|
530
|
+
*/
|
|
531
|
+
invites: {
|
|
532
|
+
/** GET /env/tenants/{tenantId}/invites — every invite with its status, newest first. */
|
|
533
|
+
list: (tenantId) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}/invites`, { envBearer: true }),
|
|
534
|
+
/**
|
|
535
|
+
* POST /env/tenants/{tenantId}/invites — invite an address. Always
|
|
536
|
+
* returns `acceptUrl`; with `sendEmail: false` Authyon does not mail
|
|
537
|
+
* it and you deliver the link yourself. Valid 7 days, single use, and
|
|
538
|
+
* not readable again later.
|
|
539
|
+
*/
|
|
540
|
+
create: (tenantId, input) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}/invites`, {
|
|
541
|
+
method: "POST",
|
|
542
|
+
envBearer: true,
|
|
543
|
+
body: {
|
|
544
|
+
email: input.email,
|
|
545
|
+
roles: input.roles,
|
|
546
|
+
sendEmail: input.sendEmail ?? true,
|
|
547
|
+
redirectUri: input.redirectUri
|
|
548
|
+
}
|
|
549
|
+
}),
|
|
550
|
+
/** POST .../invites/{inviteId}/resend — new link (the previous one stops working), mailed unless `sendEmail` is `false`. */
|
|
551
|
+
resend: (tenantId, inviteId, input = {}) => this.request(
|
|
552
|
+
`/env/tenants/${encodeURIComponent(tenantId)}/invites/${encodeURIComponent(inviteId)}/resend`,
|
|
553
|
+
{ method: "POST", envBearer: true, body: { sendEmail: input.sendEmail ?? true } }
|
|
554
|
+
),
|
|
555
|
+
/** DELETE /env/tenants/{tenantId}/invites/{inviteId} — revoke a pending invite. */
|
|
556
|
+
revoke: (tenantId, inviteId) => this.request(
|
|
557
|
+
`/env/tenants/${encodeURIComponent(tenantId)}/invites/${encodeURIComponent(inviteId)}`,
|
|
558
|
+
{ method: "DELETE", envBearer: true }
|
|
559
|
+
),
|
|
560
|
+
/**
|
|
561
|
+
* POST /auth/tenant-invites/preview — for a backend hosting the accept
|
|
562
|
+
* page. Public: needs only `envKey`, the token is the credential.
|
|
563
|
+
*/
|
|
564
|
+
preview: (token) => this.request("/auth/tenant-invites/preview", { method: "POST", body: { token } }),
|
|
565
|
+
/**
|
|
566
|
+
* Joins the tenant; for an address with no account, also creates it
|
|
567
|
+
* (password required) with the e-mail already confirmed. Does not
|
|
568
|
+
* sign the user in.
|
|
569
|
+
*
|
|
570
|
+
* Without metadata: POST /auth/tenant-invites/accept — public, needs
|
|
571
|
+
* only `envKey`. With `publicMetadata`/`privateMetadata`: POST
|
|
572
|
+
* /env/tenant-invites/accept with the environment credential
|
|
573
|
+
* (`authyon:users:write`), since only your backend may set them.
|
|
574
|
+
*/
|
|
575
|
+
accept: (input) => input.publicMetadata !== void 0 || input.privateMetadata !== void 0 ? this.request("/env/tenant-invites/accept", {
|
|
576
|
+
method: "POST",
|
|
577
|
+
envBearer: true,
|
|
578
|
+
body: input
|
|
579
|
+
}) : this.request("/auth/tenant-invites/accept", { method: "POST", body: input })
|
|
580
|
+
},
|
|
487
581
|
roles: {
|
|
488
582
|
/** GET /env/tenants/{tenantId}/roles — list a tenant's roles. */
|
|
489
583
|
list: (tenantId) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}/roles`, { envBearer: true }),
|
|
@@ -555,8 +649,9 @@ var AuthyonServerClient = class {
|
|
|
555
649
|
};
|
|
556
650
|
// ── Security: one-time codes and approvals ───────────────────────────────
|
|
557
651
|
//
|
|
558
|
-
// Everything here runs with the environment credential
|
|
559
|
-
// `authyon:
|
|
652
|
+
// Everything here runs with the environment credential: `otp` needs the
|
|
653
|
+
// `authyon:otp:verify` scope, `approvals` needs `authyon:financial:authorize`.
|
|
654
|
+
// Keep those credentials on the server.
|
|
560
655
|
this.security = {
|
|
561
656
|
otp: {
|
|
562
657
|
/**
|
|
@@ -564,7 +659,8 @@ var AuthyonServerClient = class {
|
|
|
564
659
|
* app (TOTP) code. A wrong code returns `{ valid: false }` instead of
|
|
565
660
|
* throwing. Each code is accepted once; 3 wrong codes in a row sign the
|
|
566
661
|
* user out everywhere (`sessionsRevoked: true`); 5 lock the check for 15
|
|
567
|
-
* minutes (`rate_limited`).
|
|
662
|
+
* minutes (`rate_limited`). More than 50 wrong codes in 10 minutes from the
|
|
663
|
+
* same credential pause it (`credential_throttled`). Needs `authyon:otp:verify`.
|
|
568
664
|
*/
|
|
569
665
|
check: (userId, code) => this.request(`/env/users/${segment(userId)}/otp/verify`, {
|
|
570
666
|
method: "POST",
|
|
@@ -728,6 +824,28 @@ var AuthyonServerClient = class {
|
|
|
728
824
|
_clientSecret = new WeakMap();
|
|
729
825
|
var TenantScopedClient = class {
|
|
730
826
|
constructor(server, credentials) {
|
|
827
|
+
/** Invites to the token's tenant, by e-mail or by link. */
|
|
828
|
+
this.invites = {
|
|
829
|
+
/** GET /tenant/invites — every invite with its status, newest first. */
|
|
830
|
+
list: () => this.request("/tenant/invites"),
|
|
831
|
+
/** POST /tenant/invites — always returns `acceptUrl`; `sendEmail: false` skips the e-mail. */
|
|
832
|
+
create: (input) => this.request("/tenant/invites", {
|
|
833
|
+
method: "POST",
|
|
834
|
+
body: {
|
|
835
|
+
email: input.email,
|
|
836
|
+
roles: input.roles,
|
|
837
|
+
sendEmail: input.sendEmail ?? true,
|
|
838
|
+
redirectUri: input.redirectUri
|
|
839
|
+
}
|
|
840
|
+
}),
|
|
841
|
+
/** POST /tenant/invites/{inviteId}/resend — new link (the previous one stops working), mailed unless `sendEmail` is `false`. */
|
|
842
|
+
resend: (inviteId, input = {}) => this.request(`/tenant/invites/${encodeURIComponent(inviteId)}/resend`, {
|
|
843
|
+
method: "POST",
|
|
844
|
+
body: { sendEmail: input.sendEmail ?? true }
|
|
845
|
+
}),
|
|
846
|
+
/** DELETE /tenant/invites/{inviteId} — revoke a pending invite. */
|
|
847
|
+
revoke: (inviteId) => this.request(`/tenant/invites/${encodeURIComponent(inviteId)}`, { method: "DELETE" })
|
|
848
|
+
};
|
|
731
849
|
this.members = {
|
|
732
850
|
/**
|
|
733
851
|
* GET /tenant/members — members of the token's tenant.
|
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-C0Mg5gUv.cjs';
|
|
3
|
+
import { A as AuthyonServerClient } from './authyonServerClient-1_1qNRDa.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-BvjIWPcU.js';
|
|
3
|
+
import { A as AuthyonServerClient } from './authyonServerClient-1_1qNRDa.js';
|
|
4
4
|
import 'jose';
|
|
5
5
|
|
|
6
6
|
interface ServerPermissionGuardFallbackContext {
|
package/package.json
CHANGED