authhero 9.6.0 → 9.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/authhero.cjs +154 -140
  2. package/dist/authhero.d.ts +77 -77
  3. package/dist/authhero.mjs +12932 -12792
  4. package/dist/tsconfig.types.tsbuildinfo +1 -1
  5. package/dist/types/authentication-flows/password.d.ts +1 -1
  6. package/dist/types/authentication-flows/passwordless.d.ts +6 -6
  7. package/dist/types/helpers/users.d.ts +53 -0
  8. package/dist/types/hooks/addDataHooks.d.ts +6 -0
  9. package/dist/types/index.d.ts +77 -77
  10. package/dist/types/routes/auth-api/index.d.ts +13 -13
  11. package/dist/types/routes/auth-api/oidc-logout.d.ts +2 -2
  12. package/dist/types/routes/auth-api/passwordless.d.ts +8 -8
  13. package/dist/types/routes/auth-api/register/index.d.ts +2 -2
  14. package/dist/types/routes/auth-api/well-known.d.ts +1 -1
  15. package/dist/types/routes/management-api/action-executions.d.ts +1 -1
  16. package/dist/types/routes/management-api/actions.d.ts +1 -1
  17. package/dist/types/routes/management-api/branding.d.ts +3 -3
  18. package/dist/types/routes/management-api/clients.d.ts +14 -14
  19. package/dist/types/routes/management-api/connections.d.ts +15 -15
  20. package/dist/types/routes/management-api/failed-events.d.ts +1 -1
  21. package/dist/types/routes/management-api/index.d.ts +49 -49
  22. package/dist/types/routes/management-api/logs.d.ts +4 -4
  23. package/dist/types/routes/management-api/organizations.d.ts +4 -4
  24. package/dist/types/routes/management-api/prompts.d.ts +4 -4
  25. package/dist/types/routes/management-api/tenants.d.ts +29 -29
  26. package/dist/types/routes/management-api/users.d.ts +2 -2
  27. package/dist/types/routes/universal-login/common.d.ts +8 -8
  28. package/dist/types/routes/universal-login/continue.d.ts +2 -2
  29. package/dist/types/routes/universal-login/identifier.d.ts +4 -4
  30. package/dist/types/routes/universal-login/impersonate.d.ts +2 -2
  31. package/dist/types/routes/universal-login/index.d.ts +8 -8
  32. package/dist/types/routes/universal-login/u2-index.d.ts +7 -7
  33. package/dist/types/routes/universal-login/u2-routes.d.ts +7 -7
  34. package/dist/types/utils/email.d.ts +14 -0
  35. package/dist/types/utils/jwks.d.ts +2 -2
  36. package/package.json +3 -3
@@ -37,4 +37,4 @@ export declare function changePassword(ctx: Context<{
37
37
  export declare function requestPasswordReset(ctx: Context<{
38
38
  Bindings: Bindings;
39
39
  Variables: Variables;
40
- }>, client: EnrichedClient, email: string, state: string, verification_method?: "link" | "code", routePrefix?: string): Promise<void>;
40
+ }>, client: EnrichedClient, emailInput: string, state: string, verification_method?: "link" | "code", routePrefix?: string): Promise<void>;
@@ -372,7 +372,7 @@ export declare function passwordlessGrantUser(ctx: Context<{
372
372
  active?: boolean | undefined;
373
373
  } | undefined;
374
374
  signup?: {
375
- status?: "required" | "optional" | "disabled" | undefined;
375
+ status?: "optional" | "required" | "disabled" | undefined;
376
376
  verification?: {
377
377
  active?: boolean | undefined;
378
378
  } | undefined;
@@ -389,7 +389,7 @@ export declare function passwordlessGrantUser(ctx: Context<{
389
389
  active?: boolean | undefined;
390
390
  } | undefined;
391
391
  signup?: {
392
- status?: "required" | "optional" | "disabled" | undefined;
392
+ status?: "optional" | "required" | "disabled" | undefined;
393
393
  } | undefined;
394
394
  validation?: {
395
395
  max_length?: number | undefined;
@@ -406,7 +406,7 @@ export declare function passwordlessGrantUser(ctx: Context<{
406
406
  active?: boolean | undefined;
407
407
  } | undefined;
408
408
  signup?: {
409
- status?: "required" | "optional" | "disabled" | undefined;
409
+ status?: "optional" | "required" | "disabled" | undefined;
410
410
  } | undefined;
411
411
  } | undefined;
412
412
  } | undefined;
@@ -471,7 +471,7 @@ export declare function passwordlessGrantUser(ctx: Context<{
471
471
  custom_login_page_preview?: string | undefined;
472
472
  form_template?: string | undefined;
473
473
  addons?: Record<string, any> | undefined;
474
- token_endpoint_auth_method?: "none" | "private_key_jwt" | "client_secret_post" | "client_secret_basic" | "client_secret_jwt" | undefined;
474
+ token_endpoint_auth_method?: "none" | "client_secret_post" | "client_secret_basic" | "client_secret_jwt" | "private_key_jwt" | undefined;
475
475
  client_metadata?: Record<string, string> | undefined;
476
476
  hide_sign_up_disabled_error?: boolean | undefined;
477
477
  mobile?: Record<string, any> | undefined;
@@ -554,8 +554,8 @@ export declare function passwordlessGrantUser(ctx: Context<{
554
554
  } | undefined;
555
555
  authenticated_at?: string | undefined;
556
556
  };
557
- connectionType: "username" | "sms" | "email";
558
- authConnection: "username" | "sms" | "email";
557
+ connectionType: "sms" | "email" | "username";
558
+ authConnection: "sms" | "email" | "username";
559
559
  session_id: string | undefined;
560
560
  authParams: {
561
561
  client_id: string;
@@ -3,6 +3,18 @@ import { EnrichedClient } from "./client";
3
3
  import { Context } from "hono";
4
4
  import { Bindings, Variables } from "../types";
5
5
  export declare function getUsersByEmail(userAdapter: UserDataAdapter, tenantId: string, email: string): Promise<User[]>;
6
+ /**
7
+ * Every user sharing `email`, across all pages.
8
+ *
9
+ * {@link getUsersByEmail} returns a single ten-row page, which is fine for the
10
+ * Auth0-shaped `/users-by-email` endpoint but not for a uniqueness check:
11
+ * {@link findEmailConflict} *filters* candidates by connection and cluster, so a
12
+ * truncated page can hide the one row that genuinely conflicts and let a
13
+ * duplicate through. An address legitimately spans many rows (one per provider
14
+ * in a linked cluster), so ten is well within reach. Mirrors the pagination loop
15
+ * in `resolveLinkCandidates`.
16
+ */
17
+ export declare function getAllUsersByEmail(userAdapter: UserDataAdapter, tenantId: string, email: string): Promise<User[]>;
6
18
  interface GetUserByProviderParams {
7
19
  userAdapter: UserDataAdapter;
8
20
  tenant_id: string;
@@ -128,6 +140,47 @@ export declare function repointPrimary({ userAdapter, tenant_id, formerPrimary,
128
140
  * is email-identified and neither should have its `email` rewritten by a cascade.
129
141
  */
130
142
  export declare function isEmailIdentifiedUser(user: Pick<User, "provider" | "connection">): boolean;
143
+ interface EmailConflictParams {
144
+ /** Every user sharing the new address, as returned by {@link getUsersByEmail}. */
145
+ candidates: User[];
146
+ /** The identity whose email is being changed. */
147
+ target: Pick<User, "user_id" | "provider" | "connection">;
148
+ /**
149
+ * The cluster root of the patched user. `target` may be the root itself or one
150
+ * of its linked secondaries (when the caller passed `connection`).
151
+ */
152
+ clusterRootId: string;
153
+ }
154
+ /**
155
+ * Find the user, if any, that genuinely blocks changing `target`'s email to an
156
+ * address already present on other rows.
157
+ *
158
+ * Two rows sharing an email is only a *conflict* when it makes a login ambiguous,
159
+ * and login lookups are always provider-scoped (`getUserByProvider` filters on
160
+ * `email:x provider:y`). So the check is scoped the way Auth0 scopes it — per
161
+ * connection — with one hard floor from the storage layer:
162
+ *
163
+ * - **Same provider** → always a conflict, cluster-mate or not. The
164
+ * `(tenant_id, provider, email)` unique index makes a second row with that
165
+ * address unrepresentable, so the write cannot succeed; a 409 is the honest
166
+ * answer where allowing it would surface as a constraint-violation 500.
167
+ * - **Same connection, different provider** → a conflict *between* clusters. Two
168
+ * `Username-Password-Authentication` rows (the `auth0`/`auth2` pair) sharing an
169
+ * address are competing login rows for one credential. Unknown/custom
170
+ * connections are included, so tenant-specific database connections keep the
171
+ * protection they have today.
172
+ * - **Different connection** → not a conflict. An `sms` identity is keyed by
173
+ * `phone_number` and a social identity by its provider sub, so their `email` is
174
+ * ordinary profile data that can't shadow an email login. This mirrors the
175
+ * `phone_number` carve-out on the same route (#1162) and matches Auth0, where
176
+ * one address may exist across connections.
177
+ * - **Cluster-mates** (the root and its secondaries) → not a conflict, provider
178
+ * permitting: they are the same person, and `cascadeEmailToLinkedIdentities`
179
+ * deliberately converges the cluster onto one address right after this check.
180
+ * Because AuthHero keeps secondaries as real rows (Auth0 folds them into the
181
+ * primary's `identities[]`), they'd otherwise surface here as "another user".
182
+ */
183
+ export declare function findEmailConflict({ candidates, target, clusterRootId, }: EmailConflictParams): User | undefined;
131
184
  interface CascadeEmailParams {
132
185
  userAdapter: UserDataAdapter;
133
186
  tenant_id: string;
@@ -9,6 +9,12 @@ import { Bindings, Variables } from "../types";
9
9
  * that run pre/post hooks, apply the narrow transactional commits, and
10
10
  * dispatch post-event outbox messages. `users.rawCreate` is NOT decorated —
11
11
  * commit paths call it directly to bypass the hook layer by design.
12
+ *
13
+ * `email` is lowercased on the way in so the pre-commit hooks and lookups
14
+ * (`preUserSignupHook`, the email→primary linking query) see the same
15
+ * normalized value that will be stored. Hooks can assign `email` themselves
16
+ * after this point, so the decorators normalize again just before their
17
+ * commit — see `createUserHooks` / `createUserUpdateHooks`.
12
18
  */
13
19
  export declare function addDataHooks(ctx: Context<{
14
20
  Bindings: Bindings;