authhero 8.24.0 → 8.25.1

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.
Files changed (51) hide show
  1. package/dist/assets/u/css/tailwind.css +1 -1
  2. package/dist/authhero.cjs +138 -138
  3. package/dist/authhero.css +1 -1
  4. package/dist/authhero.d.ts +667 -72
  5. package/dist/authhero.mjs +12181 -11479
  6. package/dist/tailwind.css +1 -1
  7. package/dist/tsconfig.types.tsbuildinfo +1 -1
  8. package/dist/types/authentication-flows/passwordless.d.ts +3 -3
  9. package/dist/types/components/AuthCard.d.ts +17 -0
  10. package/dist/types/components/PasswordField.d.ts +18 -0
  11. package/dist/types/components/auth-form-styles.d.ts +39 -0
  12. package/dist/types/components/auth-forms.render.test.d.ts +1 -0
  13. package/dist/types/components/ui/input.d.ts +1 -0
  14. package/dist/types/index.d.ts +74 -68
  15. package/dist/types/routes/auth-api/index.d.ts +25 -25
  16. package/dist/types/routes/auth-api/passwordless.d.ts +6 -6
  17. package/dist/types/routes/auth-api/register/index.d.ts +2 -2
  18. package/dist/types/routes/auth-api/revoke.d.ts +6 -6
  19. package/dist/types/routes/auth-api/token.d.ts +10 -10
  20. package/dist/types/routes/auth-api/well-known.d.ts +1 -1
  21. package/dist/types/routes/management-api/authentication-methods.d.ts +1 -1
  22. package/dist/types/routes/management-api/clients.d.ts +8 -8
  23. package/dist/types/routes/management-api/custom-domains.d.ts +6 -6
  24. package/dist/types/routes/management-api/guardian.d.ts +5 -5
  25. package/dist/types/routes/management-api/index.d.ts +37 -37
  26. package/dist/types/routes/management-api/logs.d.ts +4 -4
  27. package/dist/types/routes/management-api/migration-sources.d.ts +6 -6
  28. package/dist/types/routes/management-api/organizations.d.ts +1 -1
  29. package/dist/types/routes/management-api/prompts.d.ts +4 -4
  30. package/dist/types/routes/management-api/tenant-members.d.ts +304 -0
  31. package/dist/types/routes/management-api/tenant-members.test.d.ts +1 -0
  32. package/dist/types/routes/management-api/tenants.d.ts +9 -9
  33. package/dist/types/routes/management-api/users.d.ts +2 -2
  34. package/dist/types/routes/proxy-control-plane/index.d.ts +29 -0
  35. package/dist/types/routes/proxy-control-plane/scopes.d.ts +7 -0
  36. package/dist/types/routes/proxy-control-plane/tenant-members.d.ts +37 -0
  37. package/dist/types/routes/proxy-control-plane/verify.d.ts +26 -0
  38. package/dist/types/routes/proxy-control-plane/verify.test.d.ts +1 -0
  39. package/dist/types/routes/universal-login/common.d.ts +2 -2
  40. package/dist/types/routes/universal-login/u2-index.d.ts +5 -5
  41. package/dist/types/routes/universal-login/u2-routes.d.ts +5 -5
  42. package/dist/types/styles/tailwind.d.ts +1 -1
  43. package/dist/types/tenant-members/control-plane-roundtrip.test.d.ts +1 -0
  44. package/dist/types/tenant-members/local-backend.d.ts +43 -0
  45. package/dist/types/tenant-members/local-backend.test.d.ts +1 -0
  46. package/dist/types/tenant-members/remote-backend.d.ts +17 -0
  47. package/dist/types/tenant-members/types.d.ts +112 -0
  48. package/dist/types/tenant-members/wire.d.ts +28 -0
  49. package/dist/types/types/AuthHeroConfig.d.ts +37 -0
  50. package/dist/types/utils/jwks.d.ts +2 -2
  51. package/package.json +1 -1
@@ -736,9 +736,9 @@ export declare const organizationRoutes: OpenAPIHono<{
736
736
  email?: string | undefined;
737
737
  };
738
738
  id?: string | undefined;
739
- connection_id?: string | undefined;
740
739
  app_metadata?: Record<string, any> | undefined;
741
740
  user_metadata?: Record<string, any> | undefined;
741
+ connection_id?: string | undefined;
742
742
  roles?: string[] | undefined;
743
743
  ttl_sec?: number | undefined;
744
744
  send_invitation_email?: boolean | undefined;
@@ -50,7 +50,7 @@ export declare const promptsRoutes: OpenAPIHono<{
50
50
  };
51
51
  };
52
52
  output: {
53
- prompt: "mfa" | "organizations" | "signup" | "status" | "common" | "consent" | "device-flow" | "email-otp-challenge" | "email-verification" | "invitation" | "login" | "login-id" | "login-password" | "login-passwordless" | "mfa-email" | "mfa-otp" | "mfa-phone" | "mfa-login-options" | "mfa-push" | "mfa-recovery-code" | "mfa-voice" | "mfa-webauthn" | "passkeys" | "reset-password" | "signup-id" | "signup-password" | "captcha" | "custom-form";
53
+ prompt: "signup" | "status" | "mfa" | "organizations" | "login" | "login-id" | "login-password" | "signup-id" | "signup-password" | "reset-password" | "consent" | "mfa-push" | "mfa-otp" | "mfa-voice" | "mfa-phone" | "mfa-webauthn" | "mfa-email" | "mfa-recovery-code" | "device-flow" | "email-verification" | "email-otp-challenge" | "invitation" | "common" | "passkeys" | "captcha" | "custom-form" | "login-passwordless" | "mfa-login-options";
54
54
  language: string;
55
55
  }[];
56
56
  outputFormat: "json";
@@ -88,7 +88,7 @@ export declare const promptsRoutes: OpenAPIHono<{
88
88
  $get: {
89
89
  input: {
90
90
  param: {
91
- prompt: "mfa" | "organizations" | "signup" | "status" | "common" | "consent" | "device-flow" | "email-otp-challenge" | "email-verification" | "invitation" | "login" | "login-id" | "login-password" | "login-passwordless" | "mfa-email" | "mfa-otp" | "mfa-phone" | "mfa-login-options" | "mfa-push" | "mfa-recovery-code" | "mfa-voice" | "mfa-webauthn" | "passkeys" | "reset-password" | "signup-id" | "signup-password" | "captcha" | "custom-form";
91
+ prompt: "signup" | "status" | "mfa" | "organizations" | "login" | "login-id" | "login-password" | "signup-id" | "signup-password" | "reset-password" | "consent" | "mfa-push" | "mfa-otp" | "mfa-voice" | "mfa-phone" | "mfa-webauthn" | "mfa-email" | "mfa-recovery-code" | "device-flow" | "email-verification" | "email-otp-challenge" | "invitation" | "common" | "passkeys" | "captcha" | "custom-form" | "login-passwordless" | "mfa-login-options";
92
92
  language: string;
93
93
  };
94
94
  } & {
@@ -110,7 +110,7 @@ export declare const promptsRoutes: OpenAPIHono<{
110
110
  $put: {
111
111
  input: {
112
112
  param: {
113
- prompt: "mfa" | "organizations" | "signup" | "status" | "common" | "consent" | "device-flow" | "email-otp-challenge" | "email-verification" | "invitation" | "login" | "login-id" | "login-password" | "login-passwordless" | "mfa-email" | "mfa-otp" | "mfa-phone" | "mfa-login-options" | "mfa-push" | "mfa-recovery-code" | "mfa-voice" | "mfa-webauthn" | "passkeys" | "reset-password" | "signup-id" | "signup-password" | "captcha" | "custom-form";
113
+ prompt: "signup" | "status" | "mfa" | "organizations" | "login" | "login-id" | "login-password" | "signup-id" | "signup-password" | "reset-password" | "consent" | "mfa-push" | "mfa-otp" | "mfa-voice" | "mfa-phone" | "mfa-webauthn" | "mfa-email" | "mfa-recovery-code" | "device-flow" | "email-verification" | "email-otp-challenge" | "invitation" | "common" | "passkeys" | "captcha" | "custom-form" | "login-passwordless" | "mfa-login-options";
114
114
  language: string;
115
115
  };
116
116
  } & {
@@ -134,7 +134,7 @@ export declare const promptsRoutes: OpenAPIHono<{
134
134
  $delete: {
135
135
  input: {
136
136
  param: {
137
- prompt: "mfa" | "organizations" | "signup" | "status" | "common" | "consent" | "device-flow" | "email-otp-challenge" | "email-verification" | "invitation" | "login" | "login-id" | "login-password" | "login-passwordless" | "mfa-email" | "mfa-otp" | "mfa-phone" | "mfa-login-options" | "mfa-push" | "mfa-recovery-code" | "mfa-voice" | "mfa-webauthn" | "passkeys" | "reset-password" | "signup-id" | "signup-password" | "captcha" | "custom-form";
137
+ prompt: "signup" | "status" | "mfa" | "organizations" | "login" | "login-id" | "login-password" | "signup-id" | "signup-password" | "reset-password" | "consent" | "mfa-push" | "mfa-otp" | "mfa-voice" | "mfa-phone" | "mfa-webauthn" | "mfa-email" | "mfa-recovery-code" | "device-flow" | "email-verification" | "email-otp-challenge" | "invitation" | "common" | "passkeys" | "captcha" | "custom-form" | "login-passwordless" | "mfa-login-options";
138
138
  language: string;
139
139
  };
140
140
  } & {
@@ -0,0 +1,304 @@
1
+ import { OpenAPIHono } from "@hono/zod-openapi";
2
+ import { Context } from "hono";
3
+ import { Bindings, Variables } from "../../types";
4
+ import { TenantMembersBackend, tenantMemberSchema } from "../../tenant-members/types";
5
+ type Ctx = Context<{
6
+ Bindings: Bindings;
7
+ Variables: Variables;
8
+ }>;
9
+ /** Build the request's backend (local org resolution, or a control-plane hop). */
10
+ export type GetTenantMembersBackend = (ctx: Ctx) => TenantMembersBackend | Promise<TenantMembersBackend>;
11
+ /**
12
+ * `GET/POST/DELETE /api/v2/tenant-members` — lets a tenant admin manage who
13
+ * administers their tenant, from the per-tenant admin UI, without a
14
+ * control-plane login. The heavy lifting (resolving the control-plane org,
15
+ * writing membership/roles/invitations) is delegated to a
16
+ * {@link TenantMembersBackend}; this layer only pins the tenant to the token's
17
+ * org claim and shapes responses.
18
+ */
19
+ export declare function createTenantMembersRoutes(getBackend: GetTenantMembersBackend): OpenAPIHono<{
20
+ Bindings: Bindings;
21
+ Variables: Variables;
22
+ }, {
23
+ "/roles": {
24
+ $get: {
25
+ input: {
26
+ query: {
27
+ page?: unknown;
28
+ per_page?: unknown;
29
+ q?: string | undefined;
30
+ };
31
+ } & {
32
+ header: {
33
+ "tenant-id"?: string | undefined;
34
+ };
35
+ };
36
+ output: {
37
+ name: string;
38
+ id: string;
39
+ description?: string | undefined;
40
+ is_system?: boolean | undefined;
41
+ metadata?: {
42
+ [x: string]: any;
43
+ } | undefined;
44
+ created_at?: string | undefined;
45
+ updated_at?: string | undefined;
46
+ }[];
47
+ outputFormat: "json";
48
+ status: 200;
49
+ };
50
+ };
51
+ } & {
52
+ "/invitations": {
53
+ $get: {
54
+ input: {
55
+ query: {
56
+ page?: unknown;
57
+ per_page?: unknown;
58
+ q?: string | undefined;
59
+ };
60
+ } & {
61
+ header: {
62
+ "tenant-id"?: string | undefined;
63
+ };
64
+ };
65
+ output: {
66
+ id: string;
67
+ created_at: string;
68
+ expires_at: string;
69
+ client_id: string;
70
+ inviter: {
71
+ name?: string | undefined;
72
+ };
73
+ invitee: {
74
+ email?: string | undefined;
75
+ };
76
+ organization_id: string;
77
+ invitation_url: string;
78
+ ticket_id?: string | undefined;
79
+ connection_id?: string | undefined;
80
+ app_metadata?: {
81
+ [x: string]: any;
82
+ } | undefined;
83
+ user_metadata?: {
84
+ [x: string]: any;
85
+ } | undefined;
86
+ ttl_sec?: number | undefined;
87
+ roles?: string[] | undefined;
88
+ send_invitation_email?: boolean | undefined;
89
+ }[];
90
+ outputFormat: "json";
91
+ status: 200;
92
+ };
93
+ };
94
+ } & {
95
+ "/invitations": {
96
+ $post: {
97
+ input: {
98
+ header: {
99
+ "tenant-id"?: string | undefined;
100
+ };
101
+ } & {
102
+ json: {
103
+ invitee: {
104
+ email: string;
105
+ };
106
+ inviter?: {
107
+ name?: string | undefined;
108
+ } | undefined;
109
+ roles?: string[] | undefined;
110
+ send_invitation_email?: boolean | undefined;
111
+ ttl_sec?: number | undefined;
112
+ };
113
+ };
114
+ output: {
115
+ id: string;
116
+ created_at: string;
117
+ expires_at: string;
118
+ client_id: string;
119
+ inviter: {
120
+ name?: string | undefined;
121
+ };
122
+ invitee: {
123
+ email?: string | undefined;
124
+ };
125
+ organization_id: string;
126
+ invitation_url: string;
127
+ ticket_id?: string | undefined;
128
+ connection_id?: string | undefined;
129
+ app_metadata?: {
130
+ [x: string]: any;
131
+ } | undefined;
132
+ user_metadata?: {
133
+ [x: string]: any;
134
+ } | undefined;
135
+ ttl_sec?: number | undefined;
136
+ roles?: string[] | undefined;
137
+ send_invitation_email?: boolean | undefined;
138
+ };
139
+ outputFormat: "json";
140
+ status: 201;
141
+ };
142
+ };
143
+ } & {
144
+ "/invitations/:invitation_id": {
145
+ $delete: {
146
+ input: {
147
+ param: {
148
+ invitation_id: string;
149
+ };
150
+ } & {
151
+ header: {
152
+ "tenant-id"?: string | undefined;
153
+ };
154
+ };
155
+ output: {};
156
+ outputFormat: string;
157
+ status: 204;
158
+ };
159
+ };
160
+ } & {
161
+ "/": {
162
+ $get: {
163
+ input: {
164
+ query: {
165
+ page?: unknown;
166
+ per_page?: unknown;
167
+ q?: string | undefined;
168
+ };
169
+ } & {
170
+ header: {
171
+ "tenant-id"?: string | undefined;
172
+ };
173
+ };
174
+ output: {
175
+ members: {
176
+ user_id: string;
177
+ roles: {
178
+ name: string;
179
+ id: string;
180
+ description?: string | undefined;
181
+ is_system?: boolean | undefined;
182
+ metadata?: {
183
+ [x: string]: any;
184
+ } | undefined;
185
+ created_at?: string | undefined;
186
+ updated_at?: string | undefined;
187
+ }[];
188
+ email?: string | undefined;
189
+ name?: string | undefined;
190
+ picture?: string | undefined;
191
+ }[];
192
+ start: number;
193
+ limit: number;
194
+ total: number;
195
+ };
196
+ outputFormat: "json";
197
+ status: 200;
198
+ };
199
+ };
200
+ } & {
201
+ "/": {
202
+ $post: {
203
+ input: {
204
+ header: {
205
+ "tenant-id"?: string | undefined;
206
+ };
207
+ } & {
208
+ json: {
209
+ user_ids: string[];
210
+ };
211
+ };
212
+ output: {};
213
+ outputFormat: string;
214
+ status: 204;
215
+ };
216
+ };
217
+ } & {
218
+ "/": {
219
+ $delete: {
220
+ input: {
221
+ header: {
222
+ "tenant-id"?: string | undefined;
223
+ };
224
+ } & {
225
+ json: {
226
+ user_ids: string[];
227
+ };
228
+ };
229
+ output: {};
230
+ outputFormat: string;
231
+ status: 204;
232
+ };
233
+ };
234
+ } & {
235
+ "/:user_id/roles": {
236
+ $get: {
237
+ input: {
238
+ param: {
239
+ user_id: string;
240
+ };
241
+ } & {
242
+ header: {
243
+ "tenant-id"?: string | undefined;
244
+ };
245
+ };
246
+ output: {
247
+ name: string;
248
+ id: string;
249
+ description?: string | undefined;
250
+ is_system?: boolean | undefined;
251
+ metadata?: {
252
+ [x: string]: any;
253
+ } | undefined;
254
+ created_at?: string | undefined;
255
+ updated_at?: string | undefined;
256
+ }[];
257
+ outputFormat: "json";
258
+ status: 200;
259
+ };
260
+ };
261
+ } & {
262
+ "/:user_id/roles": {
263
+ $post: {
264
+ input: {
265
+ param: {
266
+ user_id: string;
267
+ };
268
+ } & {
269
+ header: {
270
+ "tenant-id"?: string | undefined;
271
+ };
272
+ } & {
273
+ json: {
274
+ roles: string[];
275
+ };
276
+ };
277
+ output: {};
278
+ outputFormat: string;
279
+ status: 204;
280
+ };
281
+ };
282
+ } & {
283
+ "/:user_id/roles": {
284
+ $delete: {
285
+ input: {
286
+ param: {
287
+ user_id: string;
288
+ };
289
+ } & {
290
+ header: {
291
+ "tenant-id"?: string | undefined;
292
+ };
293
+ } & {
294
+ json: {
295
+ roles: string[];
296
+ };
297
+ };
298
+ output: {};
299
+ outputFormat: string;
300
+ status: 204;
301
+ };
302
+ };
303
+ }, "/">;
304
+ export { tenantMemberSchema };
@@ -210,11 +210,10 @@ export declare const tenantRoutes: OpenAPIHono<{
210
210
  };
211
211
  } & {
212
212
  json: {
213
- allowed_logout_urls?: string[] | undefined;
214
- oidc_logout?: {
215
- rp_logout_end_session_endpoint_discovery?: boolean | undefined;
216
- } | undefined;
217
- default_organization?: string | undefined;
213
+ id?: string | undefined;
214
+ mtls?: {
215
+ enable_endpoint_aliases?: boolean | undefined;
216
+ } | null | undefined;
218
217
  audience?: string | undefined;
219
218
  friendly_name?: string | undefined;
220
219
  picture_url?: string | undefined;
@@ -229,6 +228,7 @@ export declare const tenantRoutes: OpenAPIHono<{
229
228
  session_cookie?: {
230
229
  mode?: "persistent" | "non-persistent" | undefined;
231
230
  } | undefined;
231
+ allowed_logout_urls?: string[] | undefined;
232
232
  default_redirection_uri?: string | undefined;
233
233
  default_client_id?: string | undefined;
234
234
  enabled_locales?: string[] | undefined;
@@ -302,15 +302,16 @@ export declare const tenantRoutes: OpenAPIHono<{
302
302
  } | undefined;
303
303
  } | null | undefined;
304
304
  default_audience?: string | undefined;
305
+ default_organization?: string | undefined;
305
306
  sessions?: {
306
307
  oidc_logout_prompt_enabled?: boolean | undefined;
307
308
  } | undefined;
309
+ oidc_logout?: {
310
+ rp_logout_end_session_endpoint_discovery?: boolean | undefined;
311
+ } | undefined;
308
312
  allow_organization_name_in_authentication_api?: boolean | undefined;
309
313
  customize_mfa_in_postlogin_action?: boolean | undefined;
310
314
  acr_values_supported?: string[] | undefined;
311
- mtls?: {
312
- enable_endpoint_aliases?: boolean | undefined;
313
- } | null | undefined;
314
315
  pushed_authorization_requests_supported?: boolean | undefined;
315
316
  authorization_response_iss_parameter_supported?: boolean | undefined;
316
317
  deployment_type?: "shared" | "wfp" | undefined;
@@ -385,7 +386,6 @@ export declare const tenantRoutes: OpenAPIHono<{
385
386
  message?: string | undefined;
386
387
  } | undefined;
387
388
  } | undefined;
388
- id?: string | undefined;
389
389
  };
390
390
  };
391
391
  output: {
@@ -809,7 +809,7 @@ export declare const userRoutes: OpenAPIHono<{
809
809
  };
810
810
  };
811
811
  output: {
812
- type: "fn" | "i" | "sapi" | "fh" | "acls_summary" | "actions_execution_failed" | "api_limit" | "api_limit_warning" | "appi" | "ciba_exchange_failed" | "ciba_exchange_succeeded" | "ciba_start_failed" | "ciba_start_succeeded" | "cls" | "cs" | "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" | "fimp" | "fi" | "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" | "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" | "sv" | "svr" | "too_many_records" | "ublkdu" | "universal_logout_failed" | "universal_logout_succeeded" | "w" | "wn" | "wum";
812
+ type: "sapi" | "fn" | "i" | "acls_summary" | "actions_execution_failed" | "api_limit" | "api_limit_warning" | "appi" | "ciba_exchange_failed" | "ciba_exchange_succeeded" | "ciba_start_failed" | "ciba_start_succeeded" | "cls" | "cs" | "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" | "fi" | "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" | "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" | "sv" | "svr" | "too_many_records" | "ublkdu" | "universal_logout_failed" | "universal_logout_succeeded" | "w" | "wn" | "wum";
813
813
  date: string;
814
814
  isMobile: boolean;
815
815
  log_id: string;
@@ -848,7 +848,7 @@ export declare const userRoutes: OpenAPIHono<{
848
848
  limit: number;
849
849
  length: number;
850
850
  logs: {
851
- type: "fn" | "i" | "sapi" | "fh" | "acls_summary" | "actions_execution_failed" | "api_limit" | "api_limit_warning" | "appi" | "ciba_exchange_failed" | "ciba_exchange_succeeded" | "ciba_start_failed" | "ciba_start_succeeded" | "cls" | "cs" | "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" | "fimp" | "fi" | "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" | "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" | "sv" | "svr" | "too_many_records" | "ublkdu" | "universal_logout_failed" | "universal_logout_succeeded" | "w" | "wn" | "wum";
851
+ type: "sapi" | "fn" | "i" | "acls_summary" | "actions_execution_failed" | "api_limit" | "api_limit_warning" | "appi" | "ciba_exchange_failed" | "ciba_exchange_succeeded" | "ciba_start_failed" | "ciba_start_succeeded" | "cls" | "cs" | "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" | "fi" | "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" | "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" | "sv" | "svr" | "too_many_records" | "ublkdu" | "universal_logout_failed" | "universal_logout_succeeded" | "w" | "wn" | "wum";
852
852
  date: string;
853
853
  isMobile: boolean;
854
854
  log_id: string;
@@ -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,22 @@ 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
+ * The second argument is the token's (unverified) `tenant_id` claim. Bind it
30
+ * to `iss` so a caller holding one tenant's subdomain key cannot act on
31
+ * another by naming it in the claim (#1143), e.g.
32
+ * `(iss, tid) => !!tid && iss === \`https://${tid}.${issuerHost}/\``. The
33
+ * binding is confirmed by the signature check the verifier runs afterwards.
34
+ */
35
+ isTrustedIssuer?: (iss: string, tenantId: string | undefined) => boolean;
19
36
  /**
20
37
  * Optional handler for `POST /sync` — receives `controlplane.sync.*` events
21
38
  * emitted by tenant shards via `ControlPlaneSyncDestination` and replicates
@@ -43,6 +60,18 @@ export interface ProxyControlPlaneOptions {
43
60
  * login.acme.com" needs a view across every tenant that only exists here.
44
61
  */
45
62
  customDomains?: CustomDomainsAdapter;
63
+ /**
64
+ * The authoritative tenant-team resource. When set, mounts
65
+ * `/api/v2/proxy/control-plane/tenant-members` — the resource tenant shards
66
+ * call through `createControlPlaneTenantMembersAdapter` to let their admins
67
+ * manage who administers the tenant (control-plane organization membership +
68
+ * org-scoped roles + invitations), rows the shard itself cannot write.
69
+ *
70
+ * Wire the backend to the control-plane database (see
71
+ * `createLocalTenantMembersBackend`); the org is pinned from the verified
72
+ * token, never the request.
73
+ */
74
+ tenantMembers?: TenantMembersControlPlaneOptions;
46
75
  }
47
76
  /**
48
77
  * Returns a Hono app exposing the privileged proxy control-plane endpoint
@@ -10,4 +10,11 @@ export declare const CONTROL_PLANE_SYNC_SCOPE = "controlplane:sync";
10
10
  * `createControlPlaneCustomDomainsAdapter`.
11
11
  */
12
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";
13
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 {};
@@ -38,6 +38,32 @@ export interface VerifyControlPlaneTokenOptions {
38
38
  * `proxy:resolve_host`.
39
39
  */
40
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
+ * `tenantId` is the token's (as-yet UNVERIFIED) `tenant_id` claim. With
55
+ * per-tenant signing keys the key owner is encoded in `iss` while the
56
+ * `tenant_id` claim is set freely by the caller, so a predicate that only
57
+ * looks at `iss` cannot stop tenant A (holding A's key) from acting on
58
+ * tenant B by claiming `tenant_id: "B"`. Bind the two here — e.g.
59
+ * `(iss, tid) => !!tid && iss === \`https://${tid}.${host}/\``. This is
60
+ * sound despite `tenant_id` being unverified at predicate time: it is the
61
+ * SAME token whose signature is checked moments later, so verification
62
+ * confirms the exact `tenant_id` the predicate bound to `iss`. A forged
63
+ * `tenant_id` either fails the predicate (mismatch with `iss`) or fails
64
+ * signature verification (the caller lacks that subdomain's key).
65
+ */
66
+ isTrustedIssuer?: (iss: string, tenantId: string | undefined) => boolean;
41
67
  }
42
68
  /**
43
69
  * Verify a bearer token for the proxy control plane. Returns `{ ok: true }`
@@ -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?: "none" | "private_key_jwt" | "client_secret_post" | "client_secret_basic" | "client_secret_jwt" | undefined;
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;
@@ -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?: "none" | "private_key_jwt" | "client_secret_post" | "client_secret_basic" | "client_secret_jwt" | undefined;
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;