authhero 8.23.1 → 8.25.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/dist/assets/u/widget/index.esm.js +1 -1
- package/dist/authhero.cjs +139 -142
- package/dist/authhero.d.ts +1073 -292
- package/dist/authhero.mjs +20321 -15480
- package/dist/tsconfig.types.tsbuildinfo +1 -1
- package/dist/types/adapters/control-plane-custom-domains.d.ts +35 -0
- package/dist/types/authentication-flows/passwordless.d.ts +4 -4
- package/dist/types/helpers/control-plane-client.d.ts +46 -0
- package/dist/types/helpers/control-plane-sync-events.d.ts +12 -28
- package/dist/types/index.d.ts +326 -246
- package/dist/types/routes/auth-api/index.d.ts +28 -28
- package/dist/types/routes/auth-api/passwordless.d.ts +12 -12
- package/dist/types/routes/auth-api/register/index.d.ts +2 -2
- package/dist/types/routes/auth-api/revoke.d.ts +2 -2
- package/dist/types/routes/auth-api/token.d.ts +12 -12
- package/dist/types/routes/management-api/authentication-methods.d.ts +1 -1
- package/dist/types/routes/management-api/clients.d.ts +14 -14
- package/dist/types/routes/management-api/connections.d.ts +16 -16
- package/dist/types/routes/management-api/custom-domains.d.ts +6 -6
- package/dist/types/routes/management-api/email-templates.d.ts +18 -18
- package/dist/types/routes/management-api/forms.d.ts +126 -126
- package/dist/types/routes/management-api/guardian.d.ts +5 -5
- package/dist/types/routes/management-api/helpers.d.ts +47 -0
- package/dist/types/routes/management-api/index.d.ts +280 -211
- package/dist/types/routes/management-api/logs.d.ts +4 -4
- package/dist/types/routes/management-api/migration-sources.d.ts +6 -6
- package/dist/types/routes/management-api/organizations.d.ts +8 -8
- package/dist/types/routes/management-api/prompts.d.ts +4 -4
- package/dist/types/routes/management-api/roles.d.ts +1 -1
- package/dist/types/routes/management-api/tenant-members.d.ts +304 -0
- package/dist/types/routes/management-api/tenant-members.test.d.ts +1 -0
- package/dist/types/routes/management-api/tenants.d.ts +8 -8
- package/dist/types/routes/management-api/users.d.ts +71 -2
- package/dist/types/routes/proxy-control-plane/custom-domains.d.ts +45 -0
- package/dist/types/routes/proxy-control-plane/index.d.ts +47 -6
- package/dist/types/routes/proxy-control-plane/scopes.d.ts +20 -0
- package/dist/types/routes/proxy-control-plane/tenant-members.d.ts +37 -0
- package/dist/types/routes/proxy-control-plane/verify.d.ts +29 -4
- package/dist/types/routes/proxy-control-plane/verify.test.d.ts +1 -0
- package/dist/types/routes/universal-login/common.d.ts +8 -8
- package/dist/types/routes/universal-login/flow-api.d.ts +12 -12
- package/dist/types/routes/universal-login/identifier.d.ts +2 -2
- package/dist/types/routes/universal-login/index.d.ts +2 -2
- package/dist/types/routes/universal-login/u2-index.d.ts +5 -5
- package/dist/types/routes/universal-login/u2-routes.d.ts +5 -5
- package/dist/types/tenant-members/control-plane-roundtrip.test.d.ts +1 -0
- package/dist/types/tenant-members/local-backend.d.ts +43 -0
- package/dist/types/tenant-members/local-backend.test.d.ts +1 -0
- package/dist/types/tenant-members/remote-backend.d.ts +17 -0
- package/dist/types/tenant-members/types.d.ts +112 -0
- package/dist/types/tenant-members/wire.d.ts +28 -0
- package/dist/types/types/AuthHeroConfig.d.ts +54 -7
- package/dist/types/types/IdToken.d.ts +4 -4
- package/package.json +6 -6
|
@@ -162,6 +162,75 @@ export declare const userRoutes: OpenAPIHono<{
|
|
|
162
162
|
}[];
|
|
163
163
|
total?: number | undefined;
|
|
164
164
|
next?: string | undefined;
|
|
165
|
+
} | {
|
|
166
|
+
users: {
|
|
167
|
+
created_at: string;
|
|
168
|
+
updated_at: string;
|
|
169
|
+
connection: string;
|
|
170
|
+
user_id: string;
|
|
171
|
+
email_verified: boolean;
|
|
172
|
+
provider: string;
|
|
173
|
+
is_social: boolean;
|
|
174
|
+
login_count: number;
|
|
175
|
+
name?: string | undefined;
|
|
176
|
+
email?: string | undefined;
|
|
177
|
+
username?: string | undefined;
|
|
178
|
+
given_name?: string | undefined;
|
|
179
|
+
phone_number?: string | undefined;
|
|
180
|
+
phone_verified?: boolean | undefined;
|
|
181
|
+
family_name?: string | undefined;
|
|
182
|
+
profileData?: string | undefined;
|
|
183
|
+
address?: {
|
|
184
|
+
formatted?: string | undefined;
|
|
185
|
+
street_address?: string | undefined;
|
|
186
|
+
locality?: string | undefined;
|
|
187
|
+
region?: string | undefined;
|
|
188
|
+
postal_code?: string | undefined;
|
|
189
|
+
country?: string | undefined;
|
|
190
|
+
} | undefined;
|
|
191
|
+
nickname?: string | undefined;
|
|
192
|
+
picture?: string | undefined;
|
|
193
|
+
locale?: string | undefined;
|
|
194
|
+
linked_to?: string | undefined;
|
|
195
|
+
app_metadata?: any;
|
|
196
|
+
user_metadata?: any;
|
|
197
|
+
middle_name?: string | undefined;
|
|
198
|
+
preferred_username?: string | undefined;
|
|
199
|
+
profile?: string | undefined;
|
|
200
|
+
website?: string | undefined;
|
|
201
|
+
gender?: string | undefined;
|
|
202
|
+
birthdate?: string | undefined;
|
|
203
|
+
zoneinfo?: string | undefined;
|
|
204
|
+
verify_email?: boolean | undefined;
|
|
205
|
+
last_ip?: string | undefined;
|
|
206
|
+
last_login?: string | undefined;
|
|
207
|
+
identities?: {
|
|
208
|
+
connection: string;
|
|
209
|
+
user_id: string;
|
|
210
|
+
provider: string;
|
|
211
|
+
isSocial: boolean;
|
|
212
|
+
email?: string | undefined;
|
|
213
|
+
email_verified?: boolean | undefined;
|
|
214
|
+
phone_number?: string | undefined;
|
|
215
|
+
phone_verified?: boolean | undefined;
|
|
216
|
+
username?: string | undefined;
|
|
217
|
+
access_token?: string | undefined;
|
|
218
|
+
access_token_secret?: string | undefined;
|
|
219
|
+
refresh_token?: string | undefined;
|
|
220
|
+
profileData?: {
|
|
221
|
+
[x: string]: any;
|
|
222
|
+
email?: string | undefined;
|
|
223
|
+
email_verified?: boolean | undefined;
|
|
224
|
+
name?: string | undefined;
|
|
225
|
+
username?: string | undefined;
|
|
226
|
+
given_name?: string | undefined;
|
|
227
|
+
phone_number?: string | undefined;
|
|
228
|
+
phone_verified?: boolean | undefined;
|
|
229
|
+
family_name?: string | undefined;
|
|
230
|
+
} | undefined;
|
|
231
|
+
}[] | undefined;
|
|
232
|
+
}[];
|
|
233
|
+
next?: string | undefined;
|
|
165
234
|
};
|
|
166
235
|
outputFormat: "json";
|
|
167
236
|
status: 200;
|
|
@@ -740,7 +809,7 @@ export declare const userRoutes: OpenAPIHono<{
|
|
|
740
809
|
};
|
|
741
810
|
};
|
|
742
811
|
output: {
|
|
743
|
-
type: "fn" | "i" | "
|
|
812
|
+
type: "fn" | "i" | "cs" | "fi" | "sv" | "acls_summary" | "actions_execution_failed" | "api_limit" | "api_limit_warning" | "appi" | "ciba_exchange_failed" | "ciba_exchange_succeeded" | "ciba_start_failed" | "ciba_start_succeeded" | "cls" | "depnote" | "f" | "fc" | "fce" | "fco" | "fcoa" | "fcp" | "fcph" | "fcpn" | "fcpr" | "fcpro" | "fcu" | "fd" | "fdeac" | "fdeaz" | "fdecc" | "fdu" | "feacft" | "feccft" | "fecte" | "fede" | "federated_logout_failed" | "fens" | "feoobft" | "feotpft" | "fepft" | "fepotpft" | "fercft" | "ferrt" | "fertft" | "festft" | "fh" | "fimp" | "flo" | "flows_execution_completed" | "flows_execution_failed" | "forms_submission_failed" | "forms_submission_succeeded" | "fp" | "fpar" | "fpurh" | "fs" | "fsa" | "fu" | "fui" | "fv" | "fvr" | "gd_auth_email_verification" | "gd_auth_fail_email_verification" | "gd_auth_failed" | "gd_auth_rejected" | "gd_auth_succeed" | "gd_enrollment_complete" | "gd_otp_rate_limit_exceed" | "gd_recovery_failed" | "gd_recovery_rate_limit_exceed" | "gd_recovery_succeed" | "gd_send_email" | "gd_send_email_verification" | "gd_send_email_verification_failure" | "gd_send_pn" | "gd_send_pn_failure" | "gd_send_sms" | "gd_send_sms_failure" | "gd_send_voice" | "gd_send_voice_failure" | "gd_start_auth" | "gd_start_enroll" | "gd_start_enroll_failed" | "gd_tenant_update" | "gd_unenroll" | "gd_update_device_account" | "gd_webauthn_challenge_failed" | "gd_webauthn_enrollment_failed" | "kms_key_management_failure" | "kms_key_management_success" | "kms_key_state_changed" | "limit_delegation" | "limit_mu" | "limit_sul" | "limit_wc" | "mfar" | "mgmt_api_read" | "my_account_authentication_method_failed" | "my_account_authentication_method_succeeded" | "oidc_backchannel_logout_failed" | "oidc_backchannel_logout_succeeded" | "organization_member_added" | "passkey_challenge_failed" | "passkey_challenge_started" | "pla" | "pwd_leak" | "reset_pwd_leak" | "resource_cleanup" | "rich_consents_access_error" | "s" | "sapi" | "fapi" | "sce" | "scoa" | "scp" | "scpn" | "scpr" | "scu" | "scv" | "sd" | "sdu" | "seacft" | "seccft" | "secte" | "sede" | "sens" | "seoobft" | "seotpft" | "sepotpft" | "sepft" | "sepkoobft" | "sepkotpft" | "sepkrcft" | "sercft" | "sertft" | "sestft" | "simp" | "si" | "signup_pwd_leak" | "slo" | "sh" | "spm" | "srrt" | "ss" | "ss_sso_failure" | "ss_sso_info" | "ss_sso_success" | "ssa" | "sscim" | "sui" | "svr" | "too_many_records" | "ublkdu" | "universal_logout_failed" | "universal_logout_succeeded" | "w" | "wn" | "wum";
|
|
744
813
|
date: string;
|
|
745
814
|
isMobile: boolean;
|
|
746
815
|
log_id: string;
|
|
@@ -779,7 +848,7 @@ export declare const userRoutes: OpenAPIHono<{
|
|
|
779
848
|
limit: number;
|
|
780
849
|
length: number;
|
|
781
850
|
logs: {
|
|
782
|
-
type: "fn" | "i" | "
|
|
851
|
+
type: "fn" | "i" | "cs" | "fi" | "sv" | "acls_summary" | "actions_execution_failed" | "api_limit" | "api_limit_warning" | "appi" | "ciba_exchange_failed" | "ciba_exchange_succeeded" | "ciba_start_failed" | "ciba_start_succeeded" | "cls" | "depnote" | "f" | "fc" | "fce" | "fco" | "fcoa" | "fcp" | "fcph" | "fcpn" | "fcpr" | "fcpro" | "fcu" | "fd" | "fdeac" | "fdeaz" | "fdecc" | "fdu" | "feacft" | "feccft" | "fecte" | "fede" | "federated_logout_failed" | "fens" | "feoobft" | "feotpft" | "fepft" | "fepotpft" | "fercft" | "ferrt" | "fertft" | "festft" | "fh" | "fimp" | "flo" | "flows_execution_completed" | "flows_execution_failed" | "forms_submission_failed" | "forms_submission_succeeded" | "fp" | "fpar" | "fpurh" | "fs" | "fsa" | "fu" | "fui" | "fv" | "fvr" | "gd_auth_email_verification" | "gd_auth_fail_email_verification" | "gd_auth_failed" | "gd_auth_rejected" | "gd_auth_succeed" | "gd_enrollment_complete" | "gd_otp_rate_limit_exceed" | "gd_recovery_failed" | "gd_recovery_rate_limit_exceed" | "gd_recovery_succeed" | "gd_send_email" | "gd_send_email_verification" | "gd_send_email_verification_failure" | "gd_send_pn" | "gd_send_pn_failure" | "gd_send_sms" | "gd_send_sms_failure" | "gd_send_voice" | "gd_send_voice_failure" | "gd_start_auth" | "gd_start_enroll" | "gd_start_enroll_failed" | "gd_tenant_update" | "gd_unenroll" | "gd_update_device_account" | "gd_webauthn_challenge_failed" | "gd_webauthn_enrollment_failed" | "kms_key_management_failure" | "kms_key_management_success" | "kms_key_state_changed" | "limit_delegation" | "limit_mu" | "limit_sul" | "limit_wc" | "mfar" | "mgmt_api_read" | "my_account_authentication_method_failed" | "my_account_authentication_method_succeeded" | "oidc_backchannel_logout_failed" | "oidc_backchannel_logout_succeeded" | "organization_member_added" | "passkey_challenge_failed" | "passkey_challenge_started" | "pla" | "pwd_leak" | "reset_pwd_leak" | "resource_cleanup" | "rich_consents_access_error" | "s" | "sapi" | "fapi" | "sce" | "scoa" | "scp" | "scpn" | "scpr" | "scu" | "scv" | "sd" | "sdu" | "seacft" | "seccft" | "secte" | "sede" | "sens" | "seoobft" | "seotpft" | "sepotpft" | "sepft" | "sepkoobft" | "sepkotpft" | "sepkrcft" | "sercft" | "sertft" | "sestft" | "simp" | "si" | "signup_pwd_leak" | "slo" | "sh" | "spm" | "srrt" | "ss" | "ss_sso_failure" | "ss_sso_info" | "ss_sso_success" | "ssa" | "sscim" | "sui" | "svr" | "too_many_records" | "ublkdu" | "universal_logout_failed" | "universal_logout_succeeded" | "w" | "wn" | "wum";
|
|
783
852
|
date: string;
|
|
784
853
|
isMobile: boolean;
|
|
785
854
|
log_id: string;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { CustomDomainsAdapter } from "@authhero/adapter-interfaces";
|
|
3
|
+
import { Bindings } from "../../types";
|
|
4
|
+
export type AuthenticateControlPlane = (c: {
|
|
5
|
+
req: {
|
|
6
|
+
raw: Request;
|
|
7
|
+
header(name: string): string | undefined;
|
|
8
|
+
url: string;
|
|
9
|
+
};
|
|
10
|
+
env: Bindings;
|
|
11
|
+
}) => Promise<{
|
|
12
|
+
ok: true;
|
|
13
|
+
tenantId?: string;
|
|
14
|
+
} | {
|
|
15
|
+
ok: false;
|
|
16
|
+
reason: string;
|
|
17
|
+
}>;
|
|
18
|
+
export interface CustomDomainsControlPlaneOptions {
|
|
19
|
+
/**
|
|
20
|
+
* The authoritative adapter. On the control plane this is the Cloudflare
|
|
21
|
+
* adapter (`@authhero/cloudflare-adapter`) wrapping the control-plane
|
|
22
|
+
* database, so a write both registers the hostname in the CF-for-SaaS zone
|
|
23
|
+
* and persists the row where the account credentials live.
|
|
24
|
+
*/
|
|
25
|
+
customDomains: CustomDomainsAdapter;
|
|
26
|
+
authenticate: AuthenticateControlPlane;
|
|
27
|
+
}
|
|
28
|
+
type TenantVars = {
|
|
29
|
+
tenantId: string;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* The authoritative `custom-domains` resource. Tenant shards reach it through
|
|
33
|
+
* `createControlPlaneCustomDomainsAdapter`; it is the only place that can both
|
|
34
|
+
* see every tenant's domains (so `login.acme.com` can be claimed exactly once)
|
|
35
|
+
* and hold the Cloudflare account credentials needed to register the hostname.
|
|
36
|
+
*
|
|
37
|
+
* Every operation is bound to the `tenant_id` claim of the verified token. The
|
|
38
|
+
* scope alone is not authorization: each shard holds it, so a request-supplied
|
|
39
|
+
* tenant id would let any shard read or delete any other tenant's domains.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createCustomDomainsControlPlaneApp(options: CustomDomainsControlPlaneOptions): Hono<{
|
|
42
|
+
Bindings: Bindings;
|
|
43
|
+
Variables: TenantVars;
|
|
44
|
+
}>;
|
|
45
|
+
export {};
|
|
@@ -3,6 +3,7 @@ import type { ResolvedHost } from "@authhero/proxy";
|
|
|
3
3
|
import { CustomDomain, CustomDomainsAdapter, ProxyRoute, ProxyRoutesAdapter } from "@authhero/adapter-interfaces";
|
|
4
4
|
import { SyncEvent } from "../../helpers/control-plane-sync-events";
|
|
5
5
|
import { Bindings } from "../../types";
|
|
6
|
+
import { type TenantMembersControlPlaneOptions } from "./tenant-members";
|
|
6
7
|
export interface ProxyControlPlaneOptions {
|
|
7
8
|
/**
|
|
8
9
|
* Cross-tenant host resolver. Typically delegated to a database adapter's
|
|
@@ -16,6 +17,16 @@ export interface ProxyControlPlaneOptions {
|
|
|
16
17
|
* service binding by inspecting the URL and dispatching accordingly.
|
|
17
18
|
*/
|
|
18
19
|
jwksFetch?: (url: string) => Promise<Response>;
|
|
20
|
+
/**
|
|
21
|
+
* Optional predicate that widens the set of accepted token issuers beyond
|
|
22
|
+
* `env.ISSUER` and the inbound host — specifically to a deployment's own
|
|
23
|
+
* Workers-for-Platforms tenant subdomains, whose per-tenant control-plane
|
|
24
|
+
* credential `jwksFetch` resolves locally (see #1139). Consulted before any
|
|
25
|
+
* JWKS fetch, so it still constrains where keys are fetched from; return
|
|
26
|
+
* `true` only for issuer hosts you serve. Applies to every mounted resource
|
|
27
|
+
* (custom-domains, tenant-members, sync).
|
|
28
|
+
*/
|
|
29
|
+
isTrustedIssuer?: (iss: string) => boolean;
|
|
19
30
|
/**
|
|
20
31
|
* Optional handler for `POST /sync` — receives `controlplane.sync.*` events
|
|
21
32
|
* emitted by tenant shards via `ControlPlaneSyncDestination` and replicates
|
|
@@ -24,10 +35,37 @@ export interface ProxyControlPlaneOptions {
|
|
|
24
35
|
*
|
|
25
36
|
* Implementations MUST be idempotent: the outbox retries on transient
|
|
26
37
|
* failures even after the receiver applied the change.
|
|
27
|
-
* `
|
|
28
|
-
*
|
|
38
|
+
* `createApplySyncEvents` wires this to a local adapter with idempotent
|
|
39
|
+
* semantics.
|
|
40
|
+
*
|
|
41
|
+
* Custom domains do NOT flow through here — the control plane is
|
|
42
|
+
* authoritative for them (see `customDomains` below); only `proxy_route`
|
|
43
|
+
* replicates upward.
|
|
29
44
|
*/
|
|
30
45
|
applySyncEvents?: (events: SyncEvent[]) => Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* The authoritative custom-domains adapter. When set, mounts the
|
|
48
|
+
* `/custom-domains` resource that tenant shards call through
|
|
49
|
+
* `createControlPlaneCustomDomainsAdapter`.
|
|
50
|
+
*
|
|
51
|
+
* Pass the Cloudflare adapter (`@authhero/cloudflare`) wrapping the
|
|
52
|
+
* control-plane database: registering a CF-for-SaaS hostname needs account
|
|
53
|
+
* credentials that only exist here, and enforcing "one tenant owns
|
|
54
|
+
* login.acme.com" needs a view across every tenant that only exists here.
|
|
55
|
+
*/
|
|
56
|
+
customDomains?: CustomDomainsAdapter;
|
|
57
|
+
/**
|
|
58
|
+
* The authoritative tenant-team resource. When set, mounts
|
|
59
|
+
* `/api/v2/proxy/control-plane/tenant-members` — the resource tenant shards
|
|
60
|
+
* call through `createControlPlaneTenantMembersAdapter` to let their admins
|
|
61
|
+
* manage who administers the tenant (control-plane organization membership +
|
|
62
|
+
* org-scoped roles + invitations), rows the shard itself cannot write.
|
|
63
|
+
*
|
|
64
|
+
* Wire the backend to the control-plane database (see
|
|
65
|
+
* `createLocalTenantMembersBackend`); the org is pinned from the verified
|
|
66
|
+
* token, never the request.
|
|
67
|
+
*/
|
|
68
|
+
tenantMembers?: TenantMembersControlPlaneOptions;
|
|
31
69
|
}
|
|
32
70
|
/**
|
|
33
71
|
* Returns a Hono app exposing the privileged proxy control-plane endpoint
|
|
@@ -46,19 +84,22 @@ export declare function createProxyControlPlaneApp(options: ProxyControlPlaneOpt
|
|
|
46
84
|
Bindings: Bindings;
|
|
47
85
|
}>;
|
|
48
86
|
export interface CreateApplySyncEventsOptions {
|
|
49
|
-
|
|
50
|
-
proxyRoutes?: ProxyRoutesAdapter;
|
|
87
|
+
proxyRoutes: ProxyRoutesAdapter;
|
|
51
88
|
}
|
|
52
89
|
/**
|
|
53
90
|
* Build an idempotent `applySyncEvents` implementation backed by a local
|
|
54
|
-
* `
|
|
55
|
-
* shapes the outbox can produce:
|
|
91
|
+
* `ProxyRoutesAdapter`. Handles the three retry shapes the outbox can produce:
|
|
56
92
|
*
|
|
57
93
|
* - duplicate `created` (retry after the previous succeeded but
|
|
58
94
|
* `markProcessed` failed) — falls back to `update`.
|
|
59
95
|
* - `updated` for a row that doesn't exist locally yet (a `created`
|
|
60
96
|
* delivery is still in flight or lost) — falls back to `create`.
|
|
61
97
|
* - `deleted` for a row that's already gone — no-op success.
|
|
98
|
+
*
|
|
99
|
+
* Custom domains are not replicated: the control plane is authoritative for
|
|
100
|
+
* them and tenant shards write through it (see
|
|
101
|
+
* `createControlPlaneCustomDomainsAdapter`), so there is no upward sync to
|
|
102
|
+
* apply.
|
|
62
103
|
*/
|
|
63
104
|
export declare function createApplySyncEvents(options: CreateApplySyncEventsOptions): (events: SyncEvent[]) => Promise<void>;
|
|
64
105
|
export type { CustomDomain, ProxyRoute };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { PROXY_RESOLVE_HOST_SCOPE } from "@authhero/proxy";
|
|
2
|
+
/**
|
|
3
|
+
* Scope carried by the tokens `ControlPlaneSyncDestination` mints for
|
|
4
|
+
* `POST /api/v2/proxy/control-plane/sync`.
|
|
5
|
+
*/
|
|
6
|
+
export declare const CONTROL_PLANE_SYNC_SCOPE = "controlplane:sync";
|
|
7
|
+
/**
|
|
8
|
+
* Scope required by the authoritative `/custom-domains` resource on the
|
|
9
|
+
* control plane. Tenant shards mint a token with this scope through
|
|
10
|
+
* `createControlPlaneCustomDomainsAdapter`.
|
|
11
|
+
*/
|
|
12
|
+
export declare const CONTROL_PLANE_CUSTOM_DOMAINS_SCOPE = "controlplane:custom_domains";
|
|
13
|
+
/**
|
|
14
|
+
* Scope required by the authoritative `/tenant-members` resource on the control
|
|
15
|
+
* plane — a tenant's team (organization membership + org-scoped roles +
|
|
16
|
+
* invitations) that only the control plane can write. Tenant shards mint a
|
|
17
|
+
* token with this scope through `createControlPlaneTenantMembersAdapter`.
|
|
18
|
+
*/
|
|
19
|
+
export declare const CONTROL_PLANE_TENANT_MEMBERS_SCOPE = "controlplane:tenant_members";
|
|
20
|
+
export { PROXY_RESOLVE_HOST_SCOPE };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Hono, type Context } from "hono";
|
|
2
|
+
import { Bindings } from "../../types";
|
|
3
|
+
import { TenantMembersBackend } from "../../tenant-members/types";
|
|
4
|
+
import type { AuthenticateControlPlane } from "./custom-domains";
|
|
5
|
+
type TenantVars = {
|
|
6
|
+
tenantId: string;
|
|
7
|
+
};
|
|
8
|
+
/** Context seen by the control-plane resource: env + the pinned tenant id. */
|
|
9
|
+
type CpCtx = Context<{
|
|
10
|
+
Bindings: Bindings;
|
|
11
|
+
Variables: TenantVars;
|
|
12
|
+
}>;
|
|
13
|
+
export interface TenantMembersControlPlaneOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Build the backend for a request. Bound to the control-plane database
|
|
16
|
+
* (`c.env.data`) and, optionally, an email sender at wire-up time. The tenant
|
|
17
|
+
* is pinned separately from the verified token, so the factory does not need
|
|
18
|
+
* it.
|
|
19
|
+
*/
|
|
20
|
+
getBackend: (c: CpCtx) => TenantMembersBackend | Promise<TenantMembersBackend>;
|
|
21
|
+
authenticate: AuthenticateControlPlane;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The authoritative `tenant-members` resource. Tenant shards reach it through
|
|
25
|
+
* `createControlPlaneTenantMembersAdapter`; it manages the control-plane
|
|
26
|
+
* organization that models a tenant's team — rows the shard cannot write.
|
|
27
|
+
*
|
|
28
|
+
* Every operation is bound to the `tenant_id` claim of the verified token. The
|
|
29
|
+
* scope alone is not authorization: each shard holds it, so a request-supplied
|
|
30
|
+
* tenant id would let any shard read or edit any other tenant's team. Mount
|
|
31
|
+
* under `/api/v2/proxy/control-plane/tenant-members`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function createTenantMembersControlPlaneApp(options: TenantMembersControlPlaneOptions): Hono<{
|
|
34
|
+
Bindings: Bindings;
|
|
35
|
+
Variables: TenantVars;
|
|
36
|
+
}>;
|
|
37
|
+
export {};
|
|
@@ -9,6 +9,13 @@ import { PROXY_RESOLVE_HOST_SCOPE } from "@authhero/proxy";
|
|
|
9
9
|
export declare function isAllowedIssuer(iss: string, expected: string): boolean;
|
|
10
10
|
export type VerifyControlPlaneTokenResult = {
|
|
11
11
|
ok: true;
|
|
12
|
+
/**
|
|
13
|
+
* The verified `tenant_id` claim, when the token carries one. Service
|
|
14
|
+
* tokens minted by `createServiceTokenCore` always do; a client-credentials
|
|
15
|
+
* token minted for a proxy may not. Callers that act on a tenant's data
|
|
16
|
+
* MUST bind to this rather than to a tenant id taken from the request.
|
|
17
|
+
*/
|
|
18
|
+
tenantId?: string;
|
|
12
19
|
} | {
|
|
13
20
|
ok: false;
|
|
14
21
|
reason: string;
|
|
@@ -25,8 +32,26 @@ export interface VerifyControlPlaneTokenOptions {
|
|
|
25
32
|
* so any host you list here must publish its own JWKS at that path.
|
|
26
33
|
*/
|
|
27
34
|
expectedIssuers: string[];
|
|
28
|
-
/**
|
|
29
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Required `scope` (the token's `scope` claim is space-separated). Pass an
|
|
37
|
+
* array to accept any one of several scopes. Defaults to
|
|
38
|
+
* `proxy:resolve_host`.
|
|
39
|
+
*/
|
|
40
|
+
requiredScope?: string | string[];
|
|
41
|
+
/**
|
|
42
|
+
* Optional predicate consulted IN ADDITION to `expectedIssuers`, for issuers
|
|
43
|
+
* that can't be enumerated ahead of time — specifically a deployment's own
|
|
44
|
+
* Workers-for-Platforms tenant subdomains (`https://{tenant}.{host}/`), whose
|
|
45
|
+
* per-tenant control-plane credential the accompanying `jwksFetch` resolves
|
|
46
|
+
* locally (see #1139).
|
|
47
|
+
*
|
|
48
|
+
* Like `expectedIssuers`, it runs BEFORE the JWKS fetch, so it still gates
|
|
49
|
+
* where the verifier will fetch keys from: return `true` only for issuer
|
|
50
|
+
* hosts you actually serve. The signature must still verify against the
|
|
51
|
+
* resolved key, so this does not broaden trust beyond "a caller holding that
|
|
52
|
+
* tenant's registered private key."
|
|
53
|
+
*/
|
|
54
|
+
isTrustedIssuer?: (iss: string) => boolean;
|
|
30
55
|
}
|
|
31
56
|
/**
|
|
32
57
|
* Verify a bearer token for the proxy control plane. Returns `{ ok: true }`
|
|
@@ -34,8 +59,8 @@ export interface VerifyControlPlaneTokenOptions {
|
|
|
34
59
|
* logs only and must not be surfaced to the caller.
|
|
35
60
|
*
|
|
36
61
|
* Accepted algs: RS256/384/512, ES256/384/512. The JWK's `alg` must match
|
|
37
|
-
* the token header's `alg`. The token must carry the configured
|
|
38
|
-
*
|
|
62
|
+
* the token header's `alg`. The token must carry one of the configured
|
|
63
|
+
* required scopes (`proxy:resolve_host` by default) and an `iss` that strictly equals
|
|
39
64
|
* one of `expectedIssuers` after URL normalization. The JWKS document is
|
|
40
65
|
* fetched from `<iss>/.well-known/jwks.json` AFTER the `iss` is allow-listed,
|
|
41
66
|
* so an attacker cannot redirect the verifier to a JWKS they control.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -357,7 +357,7 @@ export declare function initJSXRoute(ctx: Context<{
|
|
|
357
357
|
active?: boolean | undefined;
|
|
358
358
|
} | undefined;
|
|
359
359
|
signup?: {
|
|
360
|
-
status?: "
|
|
360
|
+
status?: "optional" | "required" | "disabled" | undefined;
|
|
361
361
|
verification?: {
|
|
362
362
|
active?: boolean | undefined;
|
|
363
363
|
} | undefined;
|
|
@@ -374,7 +374,7 @@ export declare function initJSXRoute(ctx: Context<{
|
|
|
374
374
|
active?: boolean | undefined;
|
|
375
375
|
} | undefined;
|
|
376
376
|
signup?: {
|
|
377
|
-
status?: "
|
|
377
|
+
status?: "optional" | "required" | "disabled" | undefined;
|
|
378
378
|
} | undefined;
|
|
379
379
|
validation?: {
|
|
380
380
|
max_length?: number | undefined;
|
|
@@ -391,7 +391,7 @@ export declare function initJSXRoute(ctx: Context<{
|
|
|
391
391
|
active?: boolean | undefined;
|
|
392
392
|
} | undefined;
|
|
393
393
|
signup?: {
|
|
394
|
-
status?: "
|
|
394
|
+
status?: "optional" | "required" | "disabled" | undefined;
|
|
395
395
|
} | undefined;
|
|
396
396
|
} | undefined;
|
|
397
397
|
} | undefined;
|
|
@@ -456,7 +456,7 @@ export declare function initJSXRoute(ctx: Context<{
|
|
|
456
456
|
custom_login_page_preview?: string | undefined;
|
|
457
457
|
form_template?: string | undefined;
|
|
458
458
|
addons?: Record<string, any> | undefined;
|
|
459
|
-
token_endpoint_auth_method?: "
|
|
459
|
+
token_endpoint_auth_method?: "client_secret_post" | "client_secret_basic" | "none" | "client_secret_jwt" | "private_key_jwt" | undefined;
|
|
460
460
|
client_metadata?: Record<string, string> | undefined;
|
|
461
461
|
hide_sign_up_disabled_error?: boolean | undefined;
|
|
462
462
|
mobile?: Record<string, any> | undefined;
|
|
@@ -1086,7 +1086,7 @@ export declare function initJSXRouteWithSession(ctx: Context<{
|
|
|
1086
1086
|
active?: boolean | undefined;
|
|
1087
1087
|
} | undefined;
|
|
1088
1088
|
signup?: {
|
|
1089
|
-
status?: "
|
|
1089
|
+
status?: "optional" | "required" | "disabled" | undefined;
|
|
1090
1090
|
verification?: {
|
|
1091
1091
|
active?: boolean | undefined;
|
|
1092
1092
|
} | undefined;
|
|
@@ -1103,7 +1103,7 @@ export declare function initJSXRouteWithSession(ctx: Context<{
|
|
|
1103
1103
|
active?: boolean | undefined;
|
|
1104
1104
|
} | undefined;
|
|
1105
1105
|
signup?: {
|
|
1106
|
-
status?: "
|
|
1106
|
+
status?: "optional" | "required" | "disabled" | undefined;
|
|
1107
1107
|
} | undefined;
|
|
1108
1108
|
validation?: {
|
|
1109
1109
|
max_length?: number | undefined;
|
|
@@ -1120,7 +1120,7 @@ export declare function initJSXRouteWithSession(ctx: Context<{
|
|
|
1120
1120
|
active?: boolean | undefined;
|
|
1121
1121
|
} | undefined;
|
|
1122
1122
|
signup?: {
|
|
1123
|
-
status?: "
|
|
1123
|
+
status?: "optional" | "required" | "disabled" | undefined;
|
|
1124
1124
|
} | undefined;
|
|
1125
1125
|
} | undefined;
|
|
1126
1126
|
} | undefined;
|
|
@@ -1185,7 +1185,7 @@ export declare function initJSXRouteWithSession(ctx: Context<{
|
|
|
1185
1185
|
custom_login_page_preview?: string | undefined;
|
|
1186
1186
|
form_template?: string | undefined;
|
|
1187
1187
|
addons?: Record<string, any> | undefined;
|
|
1188
|
-
token_endpoint_auth_method?: "
|
|
1188
|
+
token_endpoint_auth_method?: "client_secret_post" | "client_secret_basic" | "none" | "client_secret_jwt" | "private_key_jwt" | undefined;
|
|
1189
1189
|
client_metadata?: Record<string, string> | undefined;
|
|
1190
1190
|
hide_sign_up_disabled_error?: boolean | undefined;
|
|
1191
1191
|
mobile?: Record<string, any> | undefined;
|
|
@@ -27,7 +27,7 @@ export declare const flowApiRoutes: OpenAPIHono<{
|
|
|
27
27
|
output: {
|
|
28
28
|
screen: {
|
|
29
29
|
action: string;
|
|
30
|
-
method: "
|
|
30
|
+
method: "GET" | "POST";
|
|
31
31
|
components: {
|
|
32
32
|
id: string;
|
|
33
33
|
type: string;
|
|
@@ -43,7 +43,7 @@ export declare const flowApiRoutes: OpenAPIHono<{
|
|
|
43
43
|
hint?: string | undefined;
|
|
44
44
|
messages?: {
|
|
45
45
|
text: string;
|
|
46
|
-
type: "
|
|
46
|
+
type: "success" | "error" | "info" | "warning";
|
|
47
47
|
id?: number | undefined;
|
|
48
48
|
}[] | undefined;
|
|
49
49
|
}[];
|
|
@@ -51,7 +51,7 @@ export declare const flowApiRoutes: OpenAPIHono<{
|
|
|
51
51
|
description?: string | undefined;
|
|
52
52
|
messages?: {
|
|
53
53
|
text: string;
|
|
54
|
-
type: "
|
|
54
|
+
type: "success" | "error" | "info" | "warning";
|
|
55
55
|
id?: number | undefined;
|
|
56
56
|
}[] | undefined;
|
|
57
57
|
links?: {
|
|
@@ -107,7 +107,7 @@ export declare const flowApiRoutes: OpenAPIHono<{
|
|
|
107
107
|
output: {
|
|
108
108
|
screen: {
|
|
109
109
|
action: string;
|
|
110
|
-
method: "
|
|
110
|
+
method: "GET" | "POST";
|
|
111
111
|
components: {
|
|
112
112
|
id: string;
|
|
113
113
|
type: string;
|
|
@@ -123,7 +123,7 @@ export declare const flowApiRoutes: OpenAPIHono<{
|
|
|
123
123
|
hint?: string | undefined;
|
|
124
124
|
messages?: {
|
|
125
125
|
text: string;
|
|
126
|
-
type: "
|
|
126
|
+
type: "success" | "error" | "info" | "warning";
|
|
127
127
|
id?: number | undefined;
|
|
128
128
|
}[] | undefined;
|
|
129
129
|
}[];
|
|
@@ -131,7 +131,7 @@ export declare const flowApiRoutes: OpenAPIHono<{
|
|
|
131
131
|
description?: string | undefined;
|
|
132
132
|
messages?: {
|
|
133
133
|
text: string;
|
|
134
|
-
type: "
|
|
134
|
+
type: "success" | "error" | "info" | "warning";
|
|
135
135
|
id?: number | undefined;
|
|
136
136
|
}[] | undefined;
|
|
137
137
|
links?: {
|
|
@@ -204,7 +204,7 @@ export declare const flowApiRoutes: OpenAPIHono<{
|
|
|
204
204
|
output: {
|
|
205
205
|
screen: {
|
|
206
206
|
action: string;
|
|
207
|
-
method: "
|
|
207
|
+
method: "GET" | "POST";
|
|
208
208
|
components: {
|
|
209
209
|
id: string;
|
|
210
210
|
type: string;
|
|
@@ -220,7 +220,7 @@ export declare const flowApiRoutes: OpenAPIHono<{
|
|
|
220
220
|
hint?: string | undefined;
|
|
221
221
|
messages?: {
|
|
222
222
|
text: string;
|
|
223
|
-
type: "
|
|
223
|
+
type: "success" | "error" | "info" | "warning";
|
|
224
224
|
id?: number | undefined;
|
|
225
225
|
}[] | undefined;
|
|
226
226
|
}[];
|
|
@@ -228,7 +228,7 @@ export declare const flowApiRoutes: OpenAPIHono<{
|
|
|
228
228
|
description?: string | undefined;
|
|
229
229
|
messages?: {
|
|
230
230
|
text: string;
|
|
231
|
-
type: "
|
|
231
|
+
type: "success" | "error" | "info" | "warning";
|
|
232
232
|
id?: number | undefined;
|
|
233
233
|
}[] | undefined;
|
|
234
234
|
links?: {
|
|
@@ -319,7 +319,7 @@ export declare const flowApiRoutes: OpenAPIHono<{
|
|
|
319
319
|
output: {
|
|
320
320
|
screen: {
|
|
321
321
|
action: string;
|
|
322
|
-
method: "
|
|
322
|
+
method: "GET" | "POST";
|
|
323
323
|
components: {
|
|
324
324
|
id: string;
|
|
325
325
|
type: string;
|
|
@@ -335,7 +335,7 @@ export declare const flowApiRoutes: OpenAPIHono<{
|
|
|
335
335
|
hint?: string | undefined;
|
|
336
336
|
messages?: {
|
|
337
337
|
text: string;
|
|
338
|
-
type: "
|
|
338
|
+
type: "success" | "error" | "info" | "warning";
|
|
339
339
|
id?: number | undefined;
|
|
340
340
|
}[] | undefined;
|
|
341
341
|
}[];
|
|
@@ -343,7 +343,7 @@ export declare const flowApiRoutes: OpenAPIHono<{
|
|
|
343
343
|
description?: string | undefined;
|
|
344
344
|
messages?: {
|
|
345
345
|
text: string;
|
|
346
|
-
type: "
|
|
346
|
+
type: "success" | "error" | "info" | "warning";
|
|
347
347
|
id?: number | undefined;
|
|
348
348
|
}[] | undefined;
|
|
349
349
|
links?: {
|
|
@@ -30,7 +30,7 @@ export declare const identifierRoutes: OpenAPIHono<{
|
|
|
30
30
|
} & {
|
|
31
31
|
form: {
|
|
32
32
|
username: string;
|
|
33
|
-
login_selection?: "
|
|
33
|
+
login_selection?: "code" | "password" | undefined;
|
|
34
34
|
};
|
|
35
35
|
};
|
|
36
36
|
output: {};
|
|
@@ -44,7 +44,7 @@ export declare const identifierRoutes: OpenAPIHono<{
|
|
|
44
44
|
} & {
|
|
45
45
|
form: {
|
|
46
46
|
username: string;
|
|
47
|
-
login_selection?: "
|
|
47
|
+
login_selection?: "code" | "password" | undefined;
|
|
48
48
|
};
|
|
49
49
|
};
|
|
50
50
|
output: {};
|
|
@@ -515,7 +515,7 @@ export default function create(config: AuthHeroConfig): OpenAPIHono<{
|
|
|
515
515
|
} & {
|
|
516
516
|
form: {
|
|
517
517
|
username: string;
|
|
518
|
-
login_selection?: "
|
|
518
|
+
login_selection?: "code" | "password" | undefined;
|
|
519
519
|
};
|
|
520
520
|
};
|
|
521
521
|
output: {};
|
|
@@ -529,7 +529,7 @@ export default function create(config: AuthHeroConfig): OpenAPIHono<{
|
|
|
529
529
|
} & {
|
|
530
530
|
form: {
|
|
531
531
|
username: string;
|
|
532
|
-
login_selection?: "
|
|
532
|
+
login_selection?: "code" | "password" | undefined;
|
|
533
533
|
};
|
|
534
534
|
};
|
|
535
535
|
output: {};
|