use-convex 1.3.0 → 2.0.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.
Files changed (51) hide show
  1. package/README.md +104 -59
  2. package/dist/module.d.mts +62 -39
  3. package/dist/module.mjs +68 -17
  4. package/dist/runtime/auth/oauth.d.ts +96 -0
  5. package/dist/runtime/auth/oauth.js +170 -0
  6. package/dist/runtime/auth/sessionRoutes.d.ts +37 -0
  7. package/dist/runtime/auth/sessionRoutes.js +41 -0
  8. package/dist/runtime/composables/useAuth.d.ts +81 -48
  9. package/dist/runtime/composables/useAuth.js +69 -461
  10. package/dist/runtime/composables/useAuthToken.d.ts +2 -2
  11. package/dist/runtime/composables/useAuthToken.js +4 -0
  12. package/dist/runtime/composables/useConvexAuth.js +1 -1
  13. package/dist/runtime/composables/useConvexPaginatedQuery.js +6 -1
  14. package/dist/runtime/composables/useConvexQuery.js +6 -1
  15. package/dist/runtime/plugin.auth.client.d.ts +8 -3
  16. package/dist/runtime/plugin.auth.client.js +207 -31
  17. package/dist/runtime/plugin.server.js +8 -2
  18. package/dist/runtime/server/auth.d.ts +7 -2
  19. package/dist/runtime/server/auth.js +14 -3
  20. package/dist/runtime/server/convexAuth/refresh.d.ts +3 -0
  21. package/dist/runtime/server/convexAuth/refresh.js +5 -0
  22. package/dist/runtime/server/convexAuth/session.middleware.d.ts +10 -0
  23. package/dist/runtime/server/convexAuth/session.middleware.js +37 -0
  24. package/dist/runtime/server/convexAuth/setup.d.ts +21 -0
  25. package/dist/runtime/server/convexAuth/setup.js +90 -0
  26. package/dist/runtime/server/convexAuth/signin.d.ts +3 -0
  27. package/dist/runtime/server/convexAuth/signin.js +5 -0
  28. package/dist/runtime/server/convexAuth/signout.d.ts +3 -0
  29. package/dist/runtime/server/convexAuth/signout.js +5 -0
  30. package/dist/runtime/server/convexConfig.d.ts +2 -6
  31. package/dist/runtime/server/fetch.d.ts +2 -1
  32. package/dist/runtime/server/fetch.js +3 -8
  33. package/dist/runtime/utils/authClientOptions.d.ts +33 -40
  34. package/dist/runtime/utils/authClientOptions.js +1 -64
  35. package/dist/runtime/utils/authCookie.d.ts +8 -14
  36. package/dist/runtime/utils/authCookie.js +23 -27
  37. package/dist/runtime/utils/authStorage.d.ts +76 -79
  38. package/dist/runtime/utils/authStorage.js +60 -141
  39. package/dist/runtime/utils/context.d.ts +40 -3
  40. package/dist/types.d.mts +4 -2
  41. package/package.json +10 -5
  42. package/dist/runtime/server/api/convex/auth/session.d.ts +0 -36
  43. package/dist/runtime/server/api/convex/auth/session.js +0 -90
  44. package/dist/runtime/server/authCookies.d.ts +0 -9
  45. package/dist/runtime/server/authCookies.js +0 -64
  46. package/dist/runtime/server/sameOrigin.d.ts +0 -14
  47. package/dist/runtime/server/sameOrigin.js +0 -29
  48. package/dist/runtime/utils/authMutex.d.ts +0 -15
  49. package/dist/runtime/utils/authMutex.js +0 -47
  50. package/dist/runtime/utils/oauthRedirect.d.ts +0 -5
  51. package/dist/runtime/utils/oauthRedirect.js +0 -13
@@ -1,61 +1,54 @@
1
1
  /**
2
- * Runtime Convex Auth client knobs (React `ConvexAuthProvider` parity).
3
- *
4
- * Serializable defaults also live on `convex.auth` module options
5
- * (`storageNamespace`, `storage: 'localStorage' | 'inMemory'`,
6
- * `shouldHandleCode: boolean`). Call {@link configureConvexAuth} from a
7
- * client plugin (`enforce: 'pre'`) for `replaceURL`, function
8
- * `shouldHandleCode`, or a custom {@link ConvexAuthTokenStorage}.
2
+ * Runtime knobs for the Convex Auth client that can't live in serializable
3
+ * module options: a custom TokenStorage, extra ambient sign-ins, or a custom
4
+ * `replaceUrl`. Call {@link configureConvexAuth} from a client plugin with
5
+ * `enforce: 'pre'` so the options land before the auth plugin creates the
6
+ * client.
7
+ */
8
+ /**
9
+ * Token storage (`@convex-dev/auth/browser` `TokenStorage`). Methods may be
10
+ * sync or async, e.g. Capacitor Preferences or an encrypted store.
9
11
  */
10
12
  export type ConvexAuthTokenStorage = {
11
- getItem: (key: string) => string | undefined | null | Promise<string | undefined | null>;
13
+ getItem: (key: string) => string | null | undefined | Promise<string | null | undefined>;
12
14
  setItem: (key: string, value: string) => void | Promise<void>;
13
15
  removeItem: (key: string) => void | Promise<void>;
14
16
  };
15
- export type ConvexAuthStorageMode = 'localStorage' | 'inMemory';
17
+ export type { ConvexAuthStorageMode } from './authStorage.js';
18
+ /**
19
+ * An ambient sign-in registration (`AmbientSignInClient` in
20
+ * `@convex-dev/auth`): a method that finishes on its own at startup, like
21
+ * an OAuth callback. Typed loosely here so this file needs no Convex Auth
22
+ * import; the auth plugin passes it straight to `AuthClient`.
23
+ */
24
+ export type ConvexAmbientSignIn = {
25
+ id: string;
26
+ setup: (ctx: never) => void | {
27
+ onInit?: () => void;
28
+ };
29
+ };
16
30
  export type ConvexAuthClientOptions = {
17
31
  /**
18
- * When `false` (or a function returning false), ignore `?code=` OAuth
19
- * callbacks. Defaults to handling the code when a verifier is stored.
32
+ * Custom token storage. Overrides `convex.auth.storage`.
20
33
  */
21
- shouldHandleCode?: boolean | (() => boolean);
34
+ storage?: ConvexAuthTokenStorage;
22
35
  /**
23
- * Replace the URL after stripping `?code=` (JS routers). Defaults to
24
- * `history.replaceState`.
36
+ * Replaces the default ambient sign-ins (`[oauth()]`). Pass `[]` to
37
+ * disable OAuth callback handling, or include `convexOAuth()` alongside
38
+ * your own.
25
39
  */
26
- replaceURL?: (relativeUrl: string) => void | Promise<void>;
40
+ ambientSignIns?: ConvexAmbientSignIn[];
27
41
  /**
28
- * Token storage. `'localStorage'` (default), `'inMemory'`, or a custom
29
- * {@link ConvexAuthTokenStorage} (e.g. `sessionStorage`, Secure Store).
42
+ * Replace the page URL after an OAuth callback strips its params.
43
+ * Defaults to `history.replaceState`, then syncs `vue-router`.
30
44
  */
31
- storage?: ConvexAuthStorageMode | ConvexAuthTokenStorage;
32
- /**
33
- * Namespace for storage keys (non-alphanumeric chars stripped). Defaults
34
- * to the Convex deployment URL.
35
- */
36
- storageNamespace?: string;
37
- };
38
- /** Serializable subset safe for `runtimeConfig.public.convex.auth`. */
39
- export type ConvexAuthModuleClientOptions = {
40
- shouldHandleCode?: boolean;
41
- storage?: ConvexAuthStorageMode;
42
- storageNamespace?: string;
45
+ replaceUrl?: (url: string) => void;
43
46
  };
44
47
  /**
45
48
  * Set runtime Convex Auth knobs. Merge is shallow — later calls override
46
- * earlier keys. Prefer calling from a client plugin with `enforce: 'pre'`
47
- * so options land before the auth plugin consumes OAuth codes.
49
+ * earlier keys.
48
50
  */
49
51
  export declare function configureConvexAuth(options: ConvexAuthClientOptions): void;
50
- /** @internal */
51
- export declare function setConvexAuthModuleDefaults(options: ConvexAuthModuleClientOptions): void;
52
- /** Merged module defaults + {@link configureConvexAuth} overrides. */
53
52
  export declare function getConvexAuthClientOptions(): ConvexAuthClientOptions;
54
53
  /** @internal */
55
54
  export declare function resetConvexAuthClientOptionsForTests(): void;
56
- /** @internal */
57
- export declare function createInMemoryTokenStorage(): ConvexAuthTokenStorage;
58
- /** @internal */
59
- export declare function resetInMemoryTokenStorageForTests(): void;
60
- /** Resolve the active token storage from merged auth options. */
61
- export declare function resolveAuthTokenStorage(options?: ConvexAuthClientOptions): ConvexAuthTokenStorage;
@@ -1,73 +1,10 @@
1
1
  let runtimeOverrides = {};
2
- let moduleDefaults = {};
3
2
  export function configureConvexAuth(options) {
4
3
  runtimeOverrides = { ...runtimeOverrides, ...options };
5
4
  }
6
- export function setConvexAuthModuleDefaults(options) {
7
- moduleDefaults = { ...options };
8
- }
9
5
  export function getConvexAuthClientOptions() {
10
- return {
11
- ...moduleDefaults,
12
- ...runtimeOverrides
13
- };
6
+ return { ...runtimeOverrides };
14
7
  }
15
8
  export function resetConvexAuthClientOptionsForTests() {
16
9
  runtimeOverrides = {};
17
- moduleDefaults = {};
18
- }
19
- const inMemory = /* @__PURE__ */ new Map();
20
- export function createInMemoryTokenStorage() {
21
- return {
22
- getItem: (key) => inMemory.get(key) ?? null,
23
- setItem: (key, value) => {
24
- inMemory.set(key, value);
25
- },
26
- removeItem: (key) => {
27
- inMemory.delete(key);
28
- }
29
- };
30
- }
31
- export function resetInMemoryTokenStorageForTests() {
32
- inMemory.clear();
33
- }
34
- const localStorageAdapter = {
35
- getItem: (key) => {
36
- if (typeof window === "undefined") {
37
- return null;
38
- }
39
- try {
40
- return window.localStorage.getItem(key);
41
- } catch {
42
- return null;
43
- }
44
- },
45
- setItem: (key, value) => {
46
- if (typeof window === "undefined") {
47
- return;
48
- }
49
- try {
50
- window.localStorage.setItem(key, value);
51
- } catch {
52
- }
53
- },
54
- removeItem: (key) => {
55
- if (typeof window === "undefined") {
56
- return;
57
- }
58
- try {
59
- window.localStorage.removeItem(key);
60
- } catch {
61
- }
62
- }
63
- };
64
- export function resolveAuthTokenStorage(options = getConvexAuthClientOptions()) {
65
- const storage = options.storage;
66
- if (storage === "inMemory") {
67
- return createInMemoryTokenStorage();
68
- }
69
- if (storage && typeof storage === "object") {
70
- return storage;
71
- }
72
- return localStorageAdapter;
73
10
  }
@@ -1,19 +1,13 @@
1
- import { type ComputedRef } from 'vue';
1
+ import { type ComputedRef, type Ref } from 'vue';
2
2
  /**
3
- * Shared JWT cookie for SSR snapshots. Same name + options as persistTokens
4
- * so plugin reads and sign-in/out writes share one Nuxt cookie ref.
5
- *
6
- * When `auth.httpOnly` is set, this cookie is HttpOnly (server-readable only).
3
+ * Convex Auth access token shared between server and client via the Nuxt
4
+ * payload. The server fills it from the (refreshed) SSR session; the client
5
+ * auth plugin keeps it in sync with the live `AuthClient` token.
7
6
  */
7
+ export declare function useConvexAuthTokenState(): Ref<string | null>;
8
+ /** BYO providers: readable JWT cookie written by the app after sign-in. */
8
9
  export declare function useAuthJwtCookie(): import("nuxt/app").CookieRef<string | null> | undefined;
9
- /**
10
- * Readable presence marker used when JWT is HttpOnly so the client can still
11
- * compute `hasSsrSession` / `showAuthedUi` without reading the token.
12
- */
13
- export declare function useAuthPresentCookie(): import("nuxt/app").CookieRef<string | null> | undefined;
14
- /** Reactive JWT for HttpClient + SSR. Empty on the client when HttpOnly. */
10
+ /** Reactive JWT for HttpClient + SSR. */
15
11
  export declare function useSsrTokenRef(): ComputedRef<string | undefined>;
16
- /**
17
- * Session hint for UI gating: JWT readable, or HttpOnly presence cookie.
18
- */
12
+ /** Session hint for UI gating: a JWT is known for this request / client. */
19
13
  export declare function useHasSsrSessionRef(): ComputedRef<boolean>;
@@ -1,46 +1,42 @@
1
1
  import { computed } from "vue";
2
- import { useCookie, useRuntimeConfig } from "nuxt/app";
2
+ import { useCookie, useRuntimeConfig, useState } from "nuxt/app";
3
3
  import {
4
- AUTH_JWT_COOKIE_MAX_AGE,
4
+ SSR_TOKEN_STATE_KEY,
5
5
  cookieValueToSsrToken,
6
- isHttpOnlyAuth,
7
- resolveAuthCookieName,
8
- resolveAuthPresentCookieName
6
+ isConvexAuth,
7
+ resolveAuthCookieName
9
8
  } from "./authStorage.js";
10
- function cookieOptions(httpOnly) {
11
- return {
12
- sameSite: "lax",
13
- secure: process.env.NODE_ENV === "production",
14
- maxAge: AUTH_JWT_COOKIE_MAX_AGE,
15
- path: "/",
16
- httpOnly
17
- };
9
+ function readAuthConfig() {
10
+ const config = useRuntimeConfig();
11
+ return config.public.convex?.auth;
12
+ }
13
+ export function useConvexAuthTokenState() {
14
+ return useState(SSR_TOKEN_STATE_KEY, () => null);
18
15
  }
19
16
  export function useAuthJwtCookie() {
20
- const config = useRuntimeConfig();
21
- const convexConfig = config.public.convex;
22
- const name = resolveAuthCookieName(convexConfig?.auth);
23
- if (!name) {
17
+ const auth = readAuthConfig();
18
+ if (isConvexAuth(auth)) {
24
19
  return void 0;
25
20
  }
26
- const httpOnly = isHttpOnlyAuth(convexConfig?.auth);
27
- return useCookie(name, cookieOptions(httpOnly));
28
- }
29
- export function useAuthPresentCookie() {
30
- const config = useRuntimeConfig();
31
- const convexConfig = config.public.convex;
32
- const name = resolveAuthPresentCookieName(convexConfig?.auth);
21
+ const name = resolveAuthCookieName(auth);
33
22
  if (!name) {
34
23
  return void 0;
35
24
  }
36
- return useCookie(name, cookieOptions(false));
25
+ return useCookie(name, {
26
+ sameSite: "lax",
27
+ secure: process.env.NODE_ENV === "production",
28
+ path: "/"
29
+ });
37
30
  }
38
31
  export function useSsrTokenRef() {
32
+ if (isConvexAuth(readAuthConfig())) {
33
+ const state = useConvexAuthTokenState();
34
+ return computed(() => state.value || void 0);
35
+ }
39
36
  const cookie = useAuthJwtCookie();
40
37
  return computed(() => cookieValueToSsrToken(cookie?.value));
41
38
  }
42
39
  export function useHasSsrSessionRef() {
43
40
  const token = useSsrTokenRef();
44
- const present = useAuthPresentCookie();
45
- return computed(() => !!token.value || present?.value === "1");
41
+ return computed(() => !!token.value);
46
42
  }
@@ -1,96 +1,93 @@
1
1
  /**
2
- * Convex Auth client storage helpers (mirrors @convex-dev/auth/react).
2
+ * Shared auth configuration helpers.
3
+ *
4
+ * Kept free of `@convex-dev/auth` imports: apps that bring their own provider
5
+ * (Clerk, Auth0, custom JWT) load this file without installing Convex Auth.
3
6
  */
4
- import { type ConvexAuthStorageMode, type ConvexAuthTokenStorage } from './authClientOptions.js';
5
- export declare const JWT_STORAGE_KEY = "__convexAuthJWT";
6
- export declare const REFRESH_TOKEN_STORAGE_KEY = "__convexAuthRefreshToken";
7
- export declare const VERIFIER_STORAGE_KEY = "__convexAuthOAuthVerifier";
8
- export declare const AUTH_JWT_COOKIE_MAX_AGE: number;
9
- export declare const DEFAULT_CONVEX_AUTH_COOKIE = "convex_jwt";
10
- /** Readable marker so the client knows an HttpOnly session exists. */
11
- export declare const DEFAULT_AUTH_PRESENT_COOKIE = "convex_auth_present";
12
- /** HttpOnly JWT cookie (Next.js Convex Auth naming). */
13
- export declare const HTTPONLY_JWT_COOKIE = "__convexAuthJWT";
14
- /** HttpOnly refresh cookie. */
15
- export declare const HTTPONLY_REFRESH_COOKIE = "__convexAuthRefreshToken";
7
+ /** Session model for first-party Convex Auth v2. */
8
+ export type ConvexAuthMode = 'ssr' | 'spa';
9
+ /** Client token storage for Convex Auth. */
10
+ export type ConvexAuthStorageMode = 'localStorage' | 'inMemory';
11
+ /**
12
+ * Names of the session functions `setupConvexAuth` returns, as exported from
13
+ * the app's Convex functions (e.g. `convex/auth.ts` → `'auth:refreshSession'`).
14
+ */
15
+ export type ConvexAuthApiNames = {
16
+ refreshSession?: string;
17
+ signOut?: string;
18
+ isAuthenticated?: string;
19
+ };
16
20
  export type ConvexAuthConfig = {
17
- provider?: string;
18
- cookie?: string;
21
+ provider?: 'convex-auth';
19
22
  /**
20
- * Store JWT + refresh in HttpOnly cookies via Nitro (Next.js parity).
21
- * When true, JS cannot read tokens from `document.cookie`; `fetchToken`
22
- * uses same-origin POST `/api/convex/auth/session` with `{ getToken: true }`.
23
- * Prefer `true` in production. Does not make sessions XSS-proof.
24
- */
25
- httpOnly?: boolean;
26
- /** Readable presence cookie when `httpOnly` is set (UI only). */
27
- presentCookie?: string;
28
- /**
29
- * Namespace for local token keys (React `storageNamespace` parity).
30
- * Non-alphanumeric characters are stripped. Defaults to the deployment URL.
23
+ * BYO providers: cookie whose value is a JWT for SSR queries and Nitro
24
+ * `fetch*` helpers. Ignored for `provider: 'convex-auth'`, which manages
25
+ * its own cookies.
31
26
  */
27
+ cookie?: string;
28
+ /** @see ModuleAuthOptions.mode */
29
+ mode?: ConvexAuthMode;
30
+ /** @see ModuleAuthOptions.api */
31
+ api?: ConvexAuthApiNames;
32
+ /** @see ModuleAuthOptions.routePrefix */
33
+ routePrefix?: string;
34
+ /** @see ModuleAuthOptions.storageNamespace */
32
35
  storageNamespace?: string;
33
- /**
34
- * Client token storage mode. Use {@link configureConvexAuth} for a custom
35
- * {@link ConvexAuthTokenStorage}. Ignored when `httpOnly` is enabled.
36
- * @default 'localStorage'
37
- */
36
+ /** @see ModuleAuthOptions.storage */
38
37
  storage?: ConvexAuthStorageMode;
39
- /**
40
- * When `false`, do not consume `?code=` OAuth callbacks. For a function
41
- * gate, call {@link configureConvexAuth} with `shouldHandleCode`.
42
- */
43
- shouldHandleCode?: boolean;
38
+ /** @see ModuleAuthOptions.verbose */
39
+ verbose?: boolean;
40
+ };
41
+ /** Server-only Convex Auth options (`runtimeConfig.convexAuth`). */
42
+ export interface ConvexAuthServerRuntimeConfig {
43
+ /** Sign-in function names the auth proxy forwards, e.g. `'auth:signInWithUsernamePassword'`. */
44
+ signIn?: string[];
45
+ /** Origins trusted besides the request's own Host. */
46
+ allowedOrigins?: string[];
47
+ /** Cookie attributes. `secure` defaults to true except on localhost. */
48
+ cookie?: {
49
+ secure?: boolean;
50
+ domain?: string;
51
+ path?: string;
52
+ };
53
+ }
54
+ /** The Convex Auth v2 access-token cookie (fixed by `@convex-dev/auth/ssr`). */
55
+ export declare const CONVEX_AUTH_JWT_COOKIE = "__convexAuthJWT";
56
+ /** The Convex Auth v2 refresh-token cookie (fixed by `@convex-dev/auth/ssr`). */
57
+ export declare const CONVEX_AUTH_REFRESH_COOKIE = "__convexAuthRefreshToken";
58
+ export declare const DEFAULT_AUTH_ROUTE_PREFIX = "/api/convex/auth";
59
+ export declare const DEFAULT_CONVEX_AUTH_API: Required<ConvexAuthApiNames>;
60
+ /** `useState` key carrying the SSR access token to the client payload. */
61
+ export declare const SSR_TOKEN_STATE_KEY = "convex:auth-token";
62
+ export declare function isConvexAuth(auth?: ConvexAuthConfig): boolean;
63
+ /** SSR mode is the default for Convex Auth: Nuxt renders on the server. */
64
+ export declare function resolveAuthMode(auth?: ConvexAuthConfig): ConvexAuthMode;
65
+ export declare function isSsrConvexAuth(auth?: ConvexAuthConfig): boolean;
66
+ export declare function resolveAuthApiNames(auth?: ConvexAuthConfig): Required<ConvexAuthApiNames>;
67
+ export declare function resolveAuthRoutes(auth?: ConvexAuthConfig): {
68
+ signIn: string;
69
+ refresh: string;
70
+ signOut: string;
44
71
  };
45
- export type { ConvexAuthTokenStorage, ConvexAuthStorageMode };
46
- export declare function storageNamespace(urlOrNamespace: string): string;
47
- export declare function storageKey(base: string, urlOrNamespace: string): string;
48
- /**
49
- * Flatten FormData (or pass through a plain record) the same way the React
50
- * Convex Auth client does before calling `auth:signIn`.
51
- */
52
- export declare function flattenSignInParams(params?: FormData | Record<string, string>): Record<string, string>;
53
72
  /**
54
- * Resolve the auth cookie name for runtime config / SSR JWT reads.
55
- * When `provider === 'convex-auth'` and cookie is omitted, default to `convex_jwt`
56
- * (or the HttpOnly JWT name when `httpOnly` is enabled).
73
+ * Cookie holding the JWT for SSR reads: the Convex Auth access-token cookie
74
+ * in SSR mode, the configured cookie for BYO providers, otherwise none.
75
+ * Convex Auth SPA mode keeps tokens in browser storage, so it has no cookie.
57
76
  */
58
77
  export declare function resolveAuthCookieName(auth?: ConvexAuthConfig): string | undefined;
59
- export declare function resolveAuthPresentCookieName(auth?: ConvexAuthConfig): string | undefined;
60
- export declare function resolveAuthRefreshCookieName(auth?: ConvexAuthConfig): string | undefined;
61
- export declare function isHttpOnlyAuth(auth?: ConvexAuthConfig): boolean;
62
78
  /** Empty / missing cookies are not a session. */
63
79
  export declare function cookieValueToSsrToken(value: string | null | undefined): string | undefined;
64
80
  /**
65
- * Read a stored value.
66
- * Sync storage returns `string | null`. Async {@link ConvexAuthTokenStorage}
67
- * returns a Promise — callers that can wait should use {@link readLocalAsync}.
68
- */
69
- export declare function readStored(key: string): string | null | Promise<string | null>;
70
- /** Sync read. Returns null when storage is async (use {@link readLocalAsync}). */
71
- export declare function readLocal(key: string): string | null;
72
- export declare function readLocalAsync(key: string): Promise<string | null>;
73
- export declare function writeLocal(key: string, value: string | null): void;
74
- export declare function writeLocalAsync(key: string, value: string | null): Promise<void>;
75
- /**
76
- * `storage: 'inMemory'` cannot survive the IdP redirect, so the OAuth
77
- * verifier is kept in a short-lived cookie (Next.js in-memory parity).
78
- * JWTs stay in memory. Other storage modes keep the verifier with the tokens.
81
+ * Whether a JWT's `exp` claim is within `skewSeconds` of now (or unreadable).
82
+ * Signature is not checked — this only decides whether to refresh.
79
83
  */
80
- export declare function readVerifier(key: string): string | null | Promise<string | null>;
81
- export declare function readVerifierAsync(key: string): Promise<string | null>;
82
- export declare function writeVerifier(key: string, value: string | null): Promise<void>;
83
- /** @internal */
84
- export declare function readBrowserCookie(name: string): string | null;
85
- /** @internal */
86
- export declare function writeBrowserCookie(name: string, value: string | null, maxAgeSeconds: number): void;
84
+ export declare function isJwtExpiring(token: string, skewSeconds?: number, nowMs?: number): boolean;
87
85
  /**
88
- * Whether the current URL's `?code=` should be treated as an OAuth callback.
89
- * Requires a stored verifier (we started the flow). Honors
90
- * `shouldHandleCode` from module options / {@link configureConvexAuth}.
86
+ * A stable identity for the session a JWT belongs to: `iss` + `sub`.
87
+ *
88
+ * Convex Auth rotates the access token every minute but keeps the session
89
+ * id in `sub`, so this changes on sign-in / sign-out / account switch, not
90
+ * on rotation. Tokens without readable claims fall back to the token itself
91
+ * (any change is treated as a new session). Empty for no token.
91
92
  */
92
- export declare function shouldConsumeOAuthCode(options: {
93
- code: string | null;
94
- verifier: string | null;
95
- shouldHandleCode?: boolean | (() => boolean);
96
- }): boolean;
93
+ export declare function sessionKeyFromToken(token: string | null | undefined): string;
@@ -1,156 +1,75 @@
1
- import {
2
- getConvexAuthClientOptions,
3
- resolveAuthTokenStorage
4
- } from "./authClientOptions.js";
5
- export const JWT_STORAGE_KEY = "__convexAuthJWT";
6
- export const REFRESH_TOKEN_STORAGE_KEY = "__convexAuthRefreshToken";
7
- export const VERIFIER_STORAGE_KEY = "__convexAuthOAuthVerifier";
8
- export const AUTH_JWT_COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
9
- export const DEFAULT_CONVEX_AUTH_COOKIE = "convex_jwt";
10
- export const DEFAULT_AUTH_PRESENT_COOKIE = "convex_auth_present";
11
- export const HTTPONLY_JWT_COOKIE = "__convexAuthJWT";
12
- export const HTTPONLY_REFRESH_COOKIE = "__convexAuthRefreshToken";
13
- export function storageNamespace(urlOrNamespace) {
14
- return urlOrNamespace.replace(/[^a-z0-9]/gi, "");
15
- }
16
- export function storageKey(base, urlOrNamespace) {
17
- return `${base}_${storageNamespace(urlOrNamespace)}`;
18
- }
19
- export function flattenSignInParams(params) {
20
- if (params === void 0) {
21
- return {};
22
- }
23
- if (typeof FormData !== "undefined" && params instanceof FormData) {
24
- const out = {};
25
- params.forEach((value, key) => {
26
- if (typeof value === "string") {
27
- out[key] = value;
28
- }
29
- });
30
- return out;
31
- }
32
- return { ...params };
1
+ export const CONVEX_AUTH_JWT_COOKIE = "__convexAuthJWT";
2
+ export const CONVEX_AUTH_REFRESH_COOKIE = "__convexAuthRefreshToken";
3
+ export const DEFAULT_AUTH_ROUTE_PREFIX = "/api/convex/auth";
4
+ export const DEFAULT_CONVEX_AUTH_API = {
5
+ refreshSession: "auth:refreshSession",
6
+ signOut: "auth:signOut",
7
+ isAuthenticated: "auth:isAuthenticated"
8
+ };
9
+ export const SSR_TOKEN_STATE_KEY = "convex:auth-token";
10
+ export function isConvexAuth(auth) {
11
+ return auth?.provider === "convex-auth";
12
+ }
13
+ export function resolveAuthMode(auth) {
14
+ return auth?.mode ?? "ssr";
15
+ }
16
+ export function isSsrConvexAuth(auth) {
17
+ return isConvexAuth(auth) && resolveAuthMode(auth) === "ssr";
18
+ }
19
+ export function resolveAuthApiNames(auth) {
20
+ return { ...DEFAULT_CONVEX_AUTH_API, ...auth?.api };
21
+ }
22
+ export function resolveAuthRoutes(auth) {
23
+ const prefix = (auth?.routePrefix ?? DEFAULT_AUTH_ROUTE_PREFIX).replace(/\/+$/, "");
24
+ return {
25
+ signIn: `${prefix}/signin`,
26
+ refresh: `${prefix}/refresh`,
27
+ signOut: `${prefix}/signout`
28
+ };
33
29
  }
34
30
  export function resolveAuthCookieName(auth) {
35
- if (auth?.httpOnly) {
36
- return auth.cookie ?? HTTPONLY_JWT_COOKIE;
31
+ if (isConvexAuth(auth)) {
32
+ return isSsrConvexAuth(auth) ? CONVEX_AUTH_JWT_COOKIE : void 0;
37
33
  }
38
- if (auth?.cookie) {
39
- return auth.cookie;
40
- }
41
- if (auth?.provider === "convex-auth") {
42
- return DEFAULT_CONVEX_AUTH_COOKIE;
43
- }
44
- return void 0;
45
- }
46
- export function resolveAuthPresentCookieName(auth) {
47
- if (!auth?.httpOnly) {
48
- return void 0;
49
- }
50
- return auth.presentCookie ?? DEFAULT_AUTH_PRESENT_COOKIE;
51
- }
52
- export function resolveAuthRefreshCookieName(auth) {
53
- if (!auth?.httpOnly) {
54
- return void 0;
55
- }
56
- return HTTPONLY_REFRESH_COOKIE;
57
- }
58
- export function isHttpOnlyAuth(auth) {
59
- return auth?.httpOnly === true;
34
+ return auth?.cookie || void 0;
60
35
  }
61
36
  export function cookieValueToSsrToken(value) {
62
37
  return value || void 0;
63
38
  }
64
- const OAUTH_VERIFIER_MAX_AGE_SECONDS = 60 * 10;
65
- function activeStorage() {
66
- return resolveAuthTokenStorage(getConvexAuthClientOptions());
67
- }
68
- function authStorageIsInMemory() {
69
- return getConvexAuthClientOptions().storage === "inMemory";
70
- }
71
- export function readStored(key) {
72
- const value = activeStorage().getItem(key);
73
- if (value instanceof Promise) {
74
- return value.then((stored) => stored ?? null);
75
- }
76
- return value ?? null;
77
- }
78
- export function readLocal(key) {
79
- const value = readStored(key);
80
- if (value instanceof Promise) {
81
- return null;
82
- }
83
- return value;
84
- }
85
- export async function readLocalAsync(key) {
86
- return await readStored(key);
87
- }
88
- export function writeLocal(key, value) {
89
- void writeLocalAsync(key, value);
90
- }
91
- export async function writeLocalAsync(key, value) {
92
- const storage = activeStorage();
93
- if (value === null) {
94
- await storage.removeItem(key);
95
- } else {
96
- await storage.setItem(key, value);
97
- }
98
- }
99
- export function readVerifier(key) {
100
- if (authStorageIsInMemory()) {
101
- return readBrowserCookie(key);
102
- }
103
- return readStored(key);
104
- }
105
- export async function readVerifierAsync(key) {
106
- return await readVerifier(key);
107
- }
108
- export async function writeVerifier(key, value) {
109
- if (authStorageIsInMemory()) {
110
- writeBrowserCookie(key, value, OAUTH_VERIFIER_MAX_AGE_SECONDS);
111
- return;
112
- }
113
- await writeLocalAsync(key, value);
114
- }
115
- function escapeRegExp(value) {
116
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
117
- }
118
- export function readBrowserCookie(name) {
119
- if (typeof document === "undefined") {
120
- return null;
121
- }
122
- const match = document.cookie.match(new RegExp(`(?:^|; )${escapeRegExp(name)}=([^;]*)`));
123
- const raw = match?.[1];
124
- if (!raw) {
125
- return null;
39
+ export function isJwtExpiring(token, skewSeconds = 10, nowMs = Date.now()) {
40
+ const payload = token.split(".")[1];
41
+ if (!payload) {
42
+ return true;
126
43
  }
127
44
  try {
128
- return decodeURIComponent(raw);
45
+ const base64 = payload.replace(/-/g, "+").replace(/_/g, "/");
46
+ const padded = base64 + "=".repeat((4 - base64.length % 4) % 4);
47
+ const json = typeof atob === "function" ? atob(padded) : globalThis.Buffer.from(padded, "base64").toString();
48
+ const exp = JSON.parse(json).exp;
49
+ if (typeof exp !== "number") {
50
+ return true;
51
+ }
52
+ return exp * 1e3 - skewSeconds * 1e3 <= nowMs;
129
53
  } catch {
130
- return raw;
131
- }
132
- }
133
- export function writeBrowserCookie(name, value, maxAgeSeconds) {
134
- if (typeof document === "undefined") {
135
- return;
136
- }
137
- const secure = typeof location !== "undefined" && location.protocol === "https:" ? "; Secure" : "";
138
- if (value === null) {
139
- document.cookie = `${name}=; Max-Age=0; Path=/; SameSite=Lax${secure}`;
140
- return;
54
+ return true;
141
55
  }
142
- document.cookie = `${name}=${encodeURIComponent(value)}; Max-Age=${maxAgeSeconds}; Path=/; SameSite=Lax${secure}`;
143
56
  }
144
- export function shouldConsumeOAuthCode(options) {
145
- if (options.code === null || options.verifier === null) {
146
- return false;
147
- }
148
- const gate = options.shouldHandleCode ?? getConvexAuthClientOptions().shouldHandleCode;
149
- if (gate === void 0) {
150
- return true;
57
+ export function sessionKeyFromToken(token) {
58
+ if (!token) {
59
+ return "";
151
60
  }
152
- if (typeof gate === "function") {
153
- return gate();
61
+ const payload = token.split(".")[1];
62
+ if (payload) {
63
+ try {
64
+ const base64 = payload.replace(/-/g, "+").replace(/_/g, "/");
65
+ const padded = base64 + "=".repeat((4 - base64.length % 4) % 4);
66
+ const json = typeof atob === "function" ? atob(padded) : globalThis.Buffer.from(padded, "base64").toString();
67
+ const claims = JSON.parse(json);
68
+ if (typeof claims.sub === "string" && claims.sub) {
69
+ return `${typeof claims.iss === "string" ? claims.iss : ""}|${claims.sub}`;
70
+ }
71
+ } catch {
72
+ }
154
73
  }
155
- return gate;
74
+ return token;
156
75
  }