authhero 9.8.0 → 9.9.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 (36) hide show
  1. package/dist/assets/u/widget/index.esm.js +1 -1
  2. package/dist/authhero.cjs +543 -344
  3. package/dist/authhero.d.ts +158 -138
  4. package/dist/authhero.mjs +12631 -12103
  5. package/dist/tsconfig.types.tsbuildinfo +1 -1
  6. package/dist/types/authentication-flows/grant-tokens.d.ts +16 -0
  7. package/dist/types/authentication-flows/passwordless.d.ts +26 -3
  8. package/dist/types/helpers/refresh-token-lifetime.d.ts +103 -0
  9. package/dist/types/helpers/revoke-session-refresh-tokens.d.ts +33 -0
  10. package/dist/types/hooks/addDataHooks.d.ts +4 -3
  11. package/dist/types/index.d.ts +158 -138
  12. package/dist/types/routes/auth-api/index.d.ts +59 -39
  13. package/dist/types/routes/auth-api/passwordless.d.ts +6 -6
  14. package/dist/types/routes/auth-api/revoke.d.ts +6 -6
  15. package/dist/types/routes/auth-api/token.d.ts +44 -24
  16. package/dist/types/routes/auth-api/well-known.d.ts +1 -1
  17. package/dist/types/routes/management-api/custom-domains.d.ts +6 -6
  18. package/dist/types/routes/management-api/failed-events.d.ts +1 -1
  19. package/dist/types/routes/management-api/forms.d.ts +126 -126
  20. package/dist/types/routes/management-api/index.d.ts +69 -69
  21. package/dist/types/routes/management-api/keys.d.ts +16 -16
  22. package/dist/types/routes/management-api/logs.d.ts +4 -4
  23. package/dist/types/routes/management-api/organizations.d.ts +2 -2
  24. package/dist/types/routes/management-api/prompts.d.ts +4 -4
  25. package/dist/types/routes/management-api/roles.d.ts +1 -1
  26. package/dist/types/routes/management-api/tenant-export-import.d.ts +5 -5
  27. package/dist/types/routes/management-api/tenants.d.ts +2 -2
  28. package/dist/types/routes/management-api/users.d.ts +17 -17
  29. package/dist/types/routes/universal-login/info-code-exchange.d.ts +27 -0
  30. package/dist/types/routes/universal-login/token-info-page.d.ts +26 -0
  31. package/dist/types/routes/universal-login/u2-index.d.ts +5 -5
  32. package/dist/types/routes/universal-login/u2-routes.d.ts +5 -5
  33. package/dist/types/state-machines/login-session.d.ts +1 -1
  34. package/dist/types/utils/email.d.ts +21 -9
  35. package/dist/types/utils/jwks.d.ts +2 -2
  36. package/package.json +8 -8
@@ -0,0 +1,16 @@
1
+ import { Context } from "hono";
2
+ import { GrantType, TokenResponse } from "@authhero/adapter-interfaces";
3
+ import { Bindings, Variables } from "../types";
4
+ import { GrantFlowResult } from "../types/GrantFlowResult";
5
+ /**
6
+ * Turn a resolved grant into wire tokens: narrow the requested scopes to what
7
+ * the user/client is actually granted for the audience, pick the token
8
+ * lifetime from the resource server, then mint the tokens.
9
+ *
10
+ * Shared by the /oauth/token endpoint and the server-side code exchange on the
11
+ * /u2/info test page so both mint identical tokens for the same grant.
12
+ */
13
+ export declare function issueTokensForGrant(ctx: Context<{
14
+ Bindings: Bindings;
15
+ Variables: Variables;
16
+ }>, grantResult: GrantFlowResult, grantType: GrantType): Promise<TokenResponse>;
@@ -1,10 +1,13 @@
1
1
  import { Context } from "hono";
2
2
  import { z } from "@hono/zod-openapi";
3
3
  import { Bindings, Variables } from "../types";
4
+ import { GrantFlowUserResult } from "../types/GrantFlowResult";
4
5
  export declare const passwordlessGrantParamsSchema: z.ZodObject<{
5
6
  client_id: z.ZodString;
6
7
  username: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
7
8
  otp: z.ZodString;
9
+ scope: z.ZodOptional<z.ZodString>;
10
+ audience: z.ZodOptional<z.ZodString>;
8
11
  authParams: z.ZodOptional<z.ZodObject<{
9
12
  client_id: z.ZodString;
10
13
  act_as: z.ZodOptional<z.ZodString>;
@@ -42,7 +45,7 @@ export declare const passwordlessGrantParamsSchema: z.ZodObject<{
42
45
  export declare function passwordlessGrantUser(ctx: Context<{
43
46
  Bindings: Bindings;
44
47
  Variables: Variables;
45
- }>, { client_id, username, otp, authParams, enforceIpCheck, }: z.input<typeof passwordlessGrantParamsSchema>): Promise<{
48
+ }>, { client_id, username, otp, scope, audience, authParams, enforceIpCheck, }: z.input<typeof passwordlessGrantParamsSchema>): Promise<{
46
49
  user: {
47
50
  connection: string;
48
51
  email_verified: boolean;
@@ -558,16 +561,16 @@ export declare function passwordlessGrantUser(ctx: Context<{
558
561
  authConnection: "username" | "email" | "sms";
559
562
  session_id: string | undefined;
560
563
  authParams: {
564
+ audience?: string | undefined;
565
+ scope?: string | undefined;
561
566
  client_id: string;
562
567
  act_as?: string | undefined;
563
568
  response_type?: import("@authhero/adapter-interfaces").AuthorizationResponseType | undefined;
564
569
  response_mode?: import("@authhero/adapter-interfaces").AuthorizationResponseMode | undefined;
565
570
  redirect_uri?: string | undefined;
566
- audience?: string | undefined;
567
571
  organization?: string | undefined;
568
572
  state?: string | undefined;
569
573
  nonce?: string | undefined;
570
- scope?: string | undefined;
571
574
  prompt?: string | undefined;
572
575
  code_challenge_method?: import("@authhero/adapter-interfaces").CodeChallengeMethod | undefined;
573
576
  code_challenge?: string | undefined;
@@ -590,6 +593,26 @@ export declare function passwordlessGrantUser(ctx: Context<{
590
593
  vendor_id?: string | undefined;
591
594
  };
592
595
  }>;
596
+ /**
597
+ * The `http://auth0.com/oauth/grant-type/passwordless/otp` grant at
598
+ * /oauth/token.
599
+ *
600
+ * Unlike the authorization-code exchange — where /authorize has already
601
+ * authenticated the login session and created a session — nothing has run for
602
+ * this login yet: /passwordless/start only stores a PENDING login session and
603
+ * an OTP. So authenticate it here, which creates the session the auth cookie
604
+ * and the refresh token below both hang off, then mint a refresh token when
605
+ * `offline_access` was requested (issue #1273).
606
+ *
607
+ * The sibling front-channel path (`passwordlessGrant`, used by
608
+ * /co/authenticate) does not go through here: createFrontChannelAuthResponse
609
+ * does both steps itself, and skips the refresh token for code flows so the
610
+ * exchange issues it instead.
611
+ */
612
+ export declare function passwordlessOtpGrant(ctx: Context<{
613
+ Bindings: Bindings;
614
+ Variables: Variables;
615
+ }>, params: z.input<typeof passwordlessGrantParamsSchema>): Promise<GrantFlowUserResult>;
593
616
  export declare function passwordlessGrant(ctx: Context<{
594
617
  Bindings: Bindings;
595
618
  Variables: Variables;
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Refresh-token lifetimes (issue #1260).
3
+ *
4
+ * Auth0 keeps refresh-token expiry and session expiry as two separate
5
+ * concepts: the former is configured per *client* (`client.refresh_token.*`,
6
+ * in seconds), the latter per *tenant* (`session_lifetime` /
7
+ * `idle_session_lifetime`, in hours). AuthHero historically derived
8
+ * refresh-token expiry from the tenant session lifetimes only, which made
9
+ * `infinite_token_lifetime` — the setting native/mobile clients rely on —
10
+ * unrepresentable.
11
+ *
12
+ * These helpers resolve the effective lifetime: per-client config wins when
13
+ * set, otherwise we fall back to the tenant-derived behaviour so existing
14
+ * tenants see no change.
15
+ */
16
+ /**
17
+ * A resolved refresh-token lifetime.
18
+ *
19
+ * - `seconds` — expires this many seconds after the anchor point.
20
+ * - `infinite` — explicitly configured never to expire.
21
+ * - `unset` — nothing configured at either level. Distinct from `infinite`
22
+ * so callers can tell "the operator asked for no expiry" from "no opinion":
23
+ * at mint both mean no expiry, but on rotation only `infinite` clears an
24
+ * expiry the parent row already carried.
25
+ */
26
+ export type RefreshTokenLifetime = {
27
+ kind: "seconds";
28
+ seconds: number;
29
+ } | {
30
+ kind: "infinite";
31
+ } | {
32
+ kind: "unset";
33
+ };
34
+ /** The subset of a client this module reads. */
35
+ export interface RefreshTokenLifetimeClient {
36
+ refresh_token?: {
37
+ expiration_type?: "expiring" | "non-expiring";
38
+ token_lifetime?: number;
39
+ infinite_token_lifetime?: boolean;
40
+ idle_token_lifetime?: number;
41
+ infinite_idle_token_lifetime?: boolean;
42
+ };
43
+ tenant: {
44
+ session_lifetime?: number;
45
+ idle_session_lifetime?: number;
46
+ };
47
+ }
48
+ /**
49
+ * Absolute ("hard") refresh-token lifetime: how long the token is valid for,
50
+ * regardless of use.
51
+ */
52
+ export declare function resolveAbsoluteRefreshTokenLifetime(client: RefreshTokenLifetimeClient): RefreshTokenLifetime;
53
+ /**
54
+ * Idle ("sliding") refresh-token lifetime: how long the token survives without
55
+ * being exchanged. Refreshed on every successful exchange.
56
+ */
57
+ export declare function resolveIdleRefreshTokenLifetime(client: RefreshTokenLifetimeClient): RefreshTokenLifetime;
58
+ /**
59
+ * Turn a lifetime into an ISO expiry timestamp measured from `from`.
60
+ * `infinite` and `unset` both yield `undefined` — no expiry column is written.
61
+ */
62
+ export declare function lifetimeToExpiresAt(lifetime: RefreshTokenLifetime, from?: number): string | undefined;
63
+ /**
64
+ * Both expiry timestamps for a freshly minted refresh token.
65
+ */
66
+ export declare function resolveRefreshTokenExpiry(client: RefreshTokenLifetimeClient, from?: number): {
67
+ expires_at?: string;
68
+ idle_expires_at?: string;
69
+ };
70
+ /**
71
+ * The idle expiry a token should carry after a successful exchange.
72
+ *
73
+ * Sliding only applies to a token that already had an idle window: a row minted
74
+ * without one is not retro-fitted with an expiry mid-life. The exception is an
75
+ * explicit `infinite` config, which clears an existing window so a client
76
+ * switched to non-expiring stops being cut off by expiries stamped earlier.
77
+ */
78
+ export declare function slideIdleExpiry(client: RefreshTokenLifetimeClient, currentIdleExpiresAt: string | undefined, from?: number): string | undefined;
79
+ /**
80
+ * The expiry columns an in-place (non-rotating) exchange should write.
81
+ *
82
+ * Three-valued per column, matching the adapter's update contract:
83
+ * `undefined` leaves the stored value alone, a string overwrites it, `null`
84
+ * clears it.
85
+ *
86
+ * Rotation reconciles a changed client config for free — the child row is
87
+ * minted from the current lifetimes — but the non-rotating path keeps handing
88
+ * back the row it was given, so it has to say so explicitly:
89
+ *
90
+ * - Idle window: slides by the resolved lifetime, and is cleared when the
91
+ * client is configured never to idle-expire. A row minted without an idle
92
+ * window is not retro-fitted with one mid-life.
93
+ * - Absolute window: never extended — refreshing must not let a bounded token
94
+ * outlive the expiry stamped at mint — and only cleared when the client is
95
+ * configured never to expire.
96
+ */
97
+ export declare function resolveExchangeExpiryUpdate(client: RefreshTokenLifetimeClient, current: {
98
+ expires_at?: string;
99
+ idle_expires_at?: string;
100
+ }, from?: number): {
101
+ expires_at?: null;
102
+ idle_expires_at?: string | null;
103
+ };
@@ -0,0 +1,33 @@
1
+ import { DataAdapters } from "@authhero/adapter-interfaces";
2
+ /**
3
+ * The parts of a session this cascade needs: its own id, which refresh tokens
4
+ * point at through `session_id`, and the login session it originated from,
5
+ * which is the only link rows minted before that column existed carry.
6
+ */
7
+ export interface RevocableSession {
8
+ id: string;
9
+ login_session_id?: string;
10
+ }
11
+ /**
12
+ * Revoke every refresh token issued under a session.
13
+ *
14
+ * Call this only where a session is *deliberately* ended — an admin revoking
15
+ * or deleting it, or a user being blocked. Natural expiry and cleanup must not
16
+ * cascade: a refresh token is designed to outlive its session, and killing
17
+ * tokens on an SSO timeout would log out every long-lived native client on
18
+ * each timeout. Revocation couples; lifetime does not.
19
+ *
20
+ * Two sweeps, run in sequence:
21
+ *
22
+ * 1. `session_id` — the ownership edge, and the one that is actually complete.
23
+ * 2. `login_id` — legacy fallback for rows minted before `session_id` existed.
24
+ * `sessions.login_session_id` records only the session's *originating*
25
+ * authorization transaction and is never repointed on SSO reuse, so on its
26
+ * own it misses every token minted during a later re-authorization. It is
27
+ * retained until pre-Stage-2 rows have aged out (#1259) and then dropped.
28
+ *
29
+ * Sequential rather than parallel because a row can match both predicates, and
30
+ * both adapters guard on `revoked_at IS NULL` — so the second sweep skips what
31
+ * the first already revoked instead of double-counting it.
32
+ */
33
+ export declare function revokeSessionRefreshTokens(data: DataAdapters, tenant_id: string, session: RevocableSession, revoked_at: string): Promise<number>;
@@ -10,9 +10,10 @@ import { Bindings, Variables } from "../types";
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
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
13
+ * `email` is normalized (trimmed and lowercased) on the way in so the
14
+ * pre-commit hooks and lookups (`preUserSignupHook`, the email→primary linking
15
+ * query) see the same normalized value that will be stored. Hooks can assign
16
+ * `email` themselves
16
17
  * after this point, so the decorators normalize again just before their
17
18
  * commit — see `createUserHooks` / `createUserUpdateHooks`.
18
19
  */