next-token-auth 1.0.0 → 1.0.2

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # next-auth-kit
1
+ # next-token-auth
2
2
 
3
3
  A production-grade authentication library for Next.js. Handles access tokens, refresh tokens, session management, and route protection — so you don't have to wire it all up yourself.
4
4
 
@@ -22,7 +22,7 @@ Most projects end up with hundreds of lines of boilerplate before a single featu
22
22
 
23
23
  ## The Solution
24
24
 
25
- `next-auth-kit` gives you a single `AuthProvider` and a set of hooks that handle the entire auth lifecycle. You configure your API endpoints once, and the library takes care of the rest:
25
+ `next-token-auth` gives you a single `AuthProvider` and a set of hooks that handle the entire auth lifecycle. You configure your API endpoints once, and the library takes care of the rest:
26
26
 
27
27
  - Tokens are stored in cookies or memory
28
28
  - Access tokens are automatically refreshed before they expire
@@ -54,13 +54,13 @@ Most projects end up with hundreds of lines of boilerplate before a single featu
54
54
  ## Installation
55
55
 
56
56
  ```bash
57
- npm install next-auth-kit
57
+ npm install next-token-auth
58
58
  # or
59
- yarn add next-auth-kit
59
+ yarn add next-token-auth
60
60
  # or
61
- pnpm add next-auth-kit
61
+ pnpm add next-token-auth
62
62
  # or
63
- bun add next-auth-kit
63
+ bun add next-token-auth
64
64
  ```
65
65
 
66
66
  **Peer dependencies** (already installed in any Next.js project):
@@ -79,7 +79,7 @@ react-dom >= 18
79
79
 
80
80
  ```ts
81
81
  // lib/auth.ts
82
- import type { AuthConfig } from "next-auth-kit";
82
+ import type { AuthConfig } from "next-token-auth";
83
83
 
84
84
  interface User {
85
85
  id: string;
@@ -120,7 +120,7 @@ export const authConfig: AuthConfig<User> = {
120
120
 
121
121
  ```tsx
122
122
  // app/layout.tsx
123
- import { AuthProvider } from "next-auth-kit/react";
123
+ import { AuthProvider } from "next-token-auth/react";
124
124
  import { authConfig } from "@/lib/auth";
125
125
 
126
126
  export default function RootLayout({ children }: { children: React.ReactNode }) {
@@ -139,7 +139,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
139
139
  ```tsx
140
140
  "use client";
141
141
 
142
- import { useAuth } from "next-auth-kit/react";
142
+ import { useAuth } from "next-token-auth/react";
143
143
 
144
144
  export default function LoginPage() {
145
145
  const { login, isLoading } = useAuth();
@@ -200,7 +200,7 @@ interface AuthConfig<User = unknown> {
200
200
 
201
201
  token: {
202
202
  storage: "cookie" | "memory";
203
- cookieName?: string; // default: "next-auth-kit.session"
203
+ cookieName?: string; // default: "next-token-auth.session"
204
204
  secure?: boolean; // default: true
205
205
  sameSite?: "strict" | "lax" | "none"; // default: "lax"
206
206
  };
@@ -293,7 +293,7 @@ Wrap App Router route handlers to require authentication:
293
293
 
294
294
  ```ts
295
295
  // app/api/profile/route.ts
296
- import { withAuth } from "next-auth-kit/server";
296
+ import { withAuth } from "next-token-auth/server";
297
297
  import { authConfig } from "@/lib/auth";
298
298
 
299
299
  export const GET = withAuth(authConfig, async (req, session) => {
@@ -311,7 +311,7 @@ Protect entire route groups at the edge using Next.js middleware:
311
311
 
312
312
  ```ts
313
313
  // middleware.ts (project root)
314
- import { authMiddleware } from "next-auth-kit/server";
314
+ import { authMiddleware } from "next-token-auth/server";
315
315
  import { authConfig } from "@/lib/auth";
316
316
 
317
317
  export const middleware = authMiddleware(authConfig);
@@ -370,7 +370,7 @@ Use this in App Router server components and API routes to read the session with
370
370
  // app/dashboard/page.tsx
371
371
  import { redirect } from "next/navigation";
372
372
  import { cookies } from "next/headers";
373
- import { getServerSession } from "next-auth-kit/server";
373
+ import { getServerSession } from "next-token-auth/server";
374
374
  import { authConfig } from "@/lib/auth";
375
375
 
376
376
  export default async function DashboardPage() {
@@ -492,7 +492,7 @@ type ExpiryInput = number | string;
492
492
  type ExpiryStrategy = "backend" | "config" | "hybrid";
493
493
  ```
494
494
 
495
- All types are exported from the root `next-auth-kit` import.
495
+ All types are exported from the root `next-token-auth` import.
496
496
 
497
497
  ---
498
498
 
package/dist/index.js CHANGED
@@ -300,7 +300,7 @@ var TokenManager = class {
300
300
  }
301
301
  // ─── Cookie helpers (client-side only) ──────────────────────────────────────
302
302
  cookieName() {
303
- return this.config.token.cookieName ?? "next-auth-kit.session";
303
+ return this.config.token.cookieName ?? "next-token-auth.session";
304
304
  }
305
305
  readFromCookie() {
306
306
  if (typeof document === "undefined") return null;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/expiry.ts","../src/core/HttpClient.ts","../src/core/SessionManager.ts","../src/utils/crypto.ts","../src/core/TokenManager.ts","../src/core/AuthClient.ts","../src/react/AuthProvider.tsx","../src/react/hooks/useAuth.ts","../src/react/hooks/useSession.ts","../src/react/hooks/useRequireAuth.ts"],"names":["createContext","useRef","useState","useEffect","useCallback","jsx","useContext"],"mappings":"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","file":"index.js","sourcesContent":["import type { ExpiryInput, ExpiryStrategy, LoginResponse } from \"../types\";\n\nconst UNIT_MAP: Record<string, number> = {\n s: 1,\n m: 60,\n h: 3600,\n d: 86400,\n w: 604800,\n};\n\n/**\n * Parses an expiry value into seconds.\n * Accepts:\n * - number → treated as seconds\n * - string → e.g. \"15m\", \"2h\", \"2d\", \"7d\", \"1w\"\n *\n * @throws if the format is unrecognised\n */\nexport function parseExpiry(input?: ExpiryInput): number {\n if (input === undefined || input === null) {\n throw new Error(\"parseExpiry: no expiry value provided\");\n }\n\n if (typeof input === \"number\") {\n if (input <= 0) throw new Error(\"parseExpiry: value must be positive\");\n return input;\n }\n\n const trimmed = input.trim();\n\n // Pure numeric string\n if (/^\\d+$/.test(trimmed)) {\n return parseInt(trimmed, 10);\n }\n\n const match = trimmed.match(/^(\\d+(?:\\.\\d+)?)\\s*([smhdw])$/i);\n if (!match) {\n throw new Error(\n `parseExpiry: unrecognised format \"${input}\". ` +\n `Expected a number or a string like \"15m\", \"2h\", \"2d\", \"7d\", \"1w\".`\n );\n }\n\n const value = parseFloat(match[1]);\n const unit = match[2].toLowerCase();\n return Math.floor(value * UNIT_MAP[unit]);\n}\n\n/**\n * Safely parses an expiry value, returning a fallback on failure.\n */\nexport function safeParseExpiry(\n input?: ExpiryInput,\n fallbackSeconds = 900\n): number {\n try {\n return parseExpiry(input);\n } catch {\n return fallbackSeconds;\n }\n}\n\n/**\n * Resolves the access token expiry timestamp (ms) from a login response\n * using the configured strategy.\n */\nexport function resolveAccessTokenExpiry(\n response: LoginResponse,\n configExpiry?: ExpiryInput,\n strategy: ExpiryStrategy = \"hybrid\"\n): number {\n const now = Date.now();\n\n const fromBackend =\n response.accessTokenExpiresIn ?? response.expiresIn ?? undefined;\n\n if (strategy === \"backend\") {\n if (fromBackend === undefined) {\n throw new Error(\n 'resolveAccessTokenExpiry: strategy is \"backend\" but API returned no expiry'\n );\n }\n return now + parseExpiry(fromBackend) * 1000;\n }\n\n if (strategy === \"config\") {\n if (configExpiry === undefined) {\n throw new Error(\n 'resolveAccessTokenExpiry: strategy is \"config\" but no expiry configured'\n );\n }\n return now + parseExpiry(configExpiry) * 1000;\n }\n\n // hybrid: backend first, fallback to config\n if (fromBackend !== undefined) {\n return now + safeParseExpiry(fromBackend) * 1000;\n }\n if (configExpiry !== undefined) {\n return now + safeParseExpiry(configExpiry) * 1000;\n }\n\n // Last resort: 15 minutes\n return now + 900 * 1000;\n}\n\n/**\n * Resolves the refresh token expiry timestamp (ms).\n */\nexport function resolveRefreshTokenExpiry(\n response: LoginResponse,\n configExpiry?: ExpiryInput,\n strategy: ExpiryStrategy = \"hybrid\"\n): number | undefined {\n const now = Date.now();\n const fromBackend = response.refreshTokenExpiresIn;\n\n if (strategy === \"backend\") {\n return fromBackend !== undefined\n ? now + parseExpiry(fromBackend) * 1000\n : undefined;\n }\n\n if (strategy === \"config\") {\n return configExpiry !== undefined\n ? now + parseExpiry(configExpiry) * 1000\n : undefined;\n }\n\n // hybrid\n if (fromBackend !== undefined) {\n return now + safeParseExpiry(fromBackend) * 1000;\n }\n if (configExpiry !== undefined) {\n return now + safeParseExpiry(configExpiry) * 1000;\n }\n\n return undefined;\n}\n","import type { AuthConfig } from \"../types\";\nimport type { TokenManager } from \"./TokenManager\";\n\ntype RefreshFn = () => Promise<boolean>;\n\n/**\n * Authenticated HTTP client that:\n * - Injects Authorization: Bearer <accessToken>\n * - Auto-refreshes on 401 and retries the original request once\n */\nexport class HttpClient {\n private readonly config: AuthConfig;\n private readonly tokenManager: TokenManager;\n private refreshFn: RefreshFn | null = null;\n private refreshPromise: Promise<boolean> | null = null;\n\n constructor(config: AuthConfig, tokenManager: TokenManager) {\n this.config = config;\n this.tokenManager = tokenManager;\n }\n\n /** Register the refresh callback (set by AuthClient to avoid circular deps) */\n setRefreshFn(fn: RefreshFn): void {\n this.refreshFn = fn;\n }\n\n /**\n * Authenticated fetch wrapper.\n * Automatically injects the Bearer token and handles 401 → refresh → retry.\n */\n async fetch(input: RequestInfo | URL, init: RequestInit = {}): Promise<Response> {\n const tokens = this.tokenManager.getTokens();\n\n const headers = new Headers(init.headers);\n if (tokens?.accessToken) {\n headers.set(\"Authorization\", `Bearer ${tokens.accessToken}`);\n }\n\n const response = await this.doFetch(input, { ...init, headers });\n\n if (response.status === 401 && this.refreshFn) {\n const refreshed = await this.deduplicatedRefresh();\n if (refreshed) {\n // Retry with new token\n const newTokens = this.tokenManager.getTokens();\n if (newTokens?.accessToken) {\n headers.set(\"Authorization\", `Bearer ${newTokens.accessToken}`);\n }\n return this.doFetch(input, { ...init, headers });\n }\n }\n\n return response;\n }\n\n /**\n * Raw fetch using the configured fetchFn or global fetch.\n */\n async doFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n const fetchFn = this.config.fetchFn ?? fetch;\n return fetchFn(input as RequestInfo, init);\n }\n\n /**\n * Builds a full URL from a path relative to baseUrl.\n */\n url(path: string): string {\n return `${this.config.baseUrl.replace(/\\/$/, \"\")}/${path.replace(/^\\//, \"\")}`;\n }\n\n // ─── Private ────────────────────────────────────────────────────────────────\n\n /**\n * Ensures only one refresh request is in-flight at a time.\n */\n private async deduplicatedRefresh(): Promise<boolean> {\n if (this.refreshPromise) return this.refreshPromise;\n\n this.refreshPromise = this.refreshFn!().finally(() => {\n this.refreshPromise = null;\n });\n\n return this.refreshPromise;\n }\n}\n","import type { AuthConfig, AuthSession, AuthTokens } from \"../types\";\nimport type { HttpClient } from \"./HttpClient\";\nimport type { TokenManager } from \"./TokenManager\";\n\n/**\n * Derives and caches the current AuthSession from stored tokens.\n * Fetches the user profile from the /me endpoint when available.\n */\nexport class SessionManager<User = unknown> {\n private session: AuthSession<User> = {\n user: null,\n tokens: null,\n isAuthenticated: false,\n };\n\n private readonly config: AuthConfig<User>;\n private readonly tokenManager: TokenManager;\n private readonly httpClient: HttpClient;\n\n constructor(\n config: AuthConfig<User>,\n tokenManager: TokenManager,\n httpClient: HttpClient\n ) {\n this.config = config;\n this.tokenManager = tokenManager;\n this.httpClient = httpClient;\n }\n\n getSession(): AuthSession<User> {\n return this.session;\n }\n\n setSession(session: AuthSession<User>): void {\n this.session = session;\n }\n\n /**\n * Builds a session from stored tokens, optionally fetching the user profile.\n */\n async loadSession(): Promise<AuthSession<User>> {\n const tokens = this.tokenManager.getTokens();\n\n if (!tokens) {\n this.session = { user: null, tokens: null, isAuthenticated: false };\n return this.session;\n }\n\n // If access token is expired and refresh is also expired, clear everything\n if (\n this.tokenManager.isAccessExpired(tokens) &&\n this.tokenManager.isRefreshExpired(tokens)\n ) {\n this.tokenManager.clearTokens();\n this.session = { user: null, tokens: null, isAuthenticated: false };\n return this.session;\n }\n\n const user = await this.fetchUser(tokens);\n this.session = {\n user,\n tokens,\n isAuthenticated: true,\n };\n\n return this.session;\n }\n\n /**\n * Updates the session after a successful token refresh.\n */\n async refreshSession(tokens: AuthTokens): Promise<void> {\n const user = this.session.user ?? (await this.fetchUser(tokens));\n this.session = { user, tokens, isAuthenticated: true };\n }\n\n clearSession(): void {\n this.session = { user: null, tokens: null, isAuthenticated: false };\n }\n\n // ─── Private ────────────────────────────────────────────────────────────────\n\n private async fetchUser(tokens: AuthTokens): Promise<User | null> {\n const meEndpoint = this.config.endpoints.me;\n if (!meEndpoint) return null;\n\n try {\n const res = await this.httpClient.fetch(this.httpClient.url(meEndpoint));\n if (!res.ok) return null;\n return (await res.json()) as User;\n } catch {\n return null;\n }\n }\n}\n","/**\n * Lightweight symmetric encryption using AES-GCM via the Web Crypto API.\n * Works in both browser and Node.js (>=18) / Edge runtimes.\n */\n\nconst ALGO = \"AES-GCM\";\nconst IV_LENGTH = 12; // bytes\n\nfunction getTextEncoder() {\n return new TextEncoder();\n}\n\nfunction getTextDecoder() {\n return new TextDecoder();\n}\n\nasync function deriveKey(secret: string): Promise<CryptoKey> {\n const raw = getTextEncoder().encode(secret.padEnd(32, \"0\").slice(0, 32));\n return crypto.subtle.importKey(\"raw\", raw, { name: ALGO }, false, [\n \"encrypt\",\n \"decrypt\",\n ]);\n}\n\n/**\n * Encrypts a plaintext string using AES-GCM.\n * Returns a base64url-encoded string: `<iv>.<ciphertext>`\n */\nexport async function encrypt(data: string, secret: string): Promise<string> {\n const key = await deriveKey(secret);\n const ivArray = crypto.getRandomValues(new Uint8Array(IV_LENGTH));\n // Ensure we have a plain ArrayBuffer for SubtleCrypto\n const iv = ivArray.buffer.slice(0, IV_LENGTH) as ArrayBuffer;\n const encoded = getTextEncoder().encode(data);\n\n const cipherBuffer = await crypto.subtle.encrypt({ name: ALGO, iv }, key, encoded);\n\n const ivB64 = bufferToBase64(new Uint8Array(iv));\n const cipherB64 = bufferToBase64(new Uint8Array(cipherBuffer));\n return `${ivB64}.${cipherB64}`;\n}\n\n/**\n * Decrypts a string produced by `encrypt`.\n */\nexport async function decrypt(data: string, secret: string): Promise<string> {\n const [ivB64, cipherB64] = data.split(\".\");\n if (!ivB64 || !cipherB64) {\n throw new Error(\"decrypt: invalid ciphertext format\");\n }\n\n const key = await deriveKey(secret);\n const ivBytes = base64ToBuffer(ivB64);\n const iv = ivBytes.buffer.slice(\n ivBytes.byteOffset,\n ivBytes.byteOffset + ivBytes.byteLength\n ) as ArrayBuffer;\n\n const cipherBytes = base64ToBuffer(cipherB64);\n const cipherBuffer = cipherBytes.buffer.slice(\n cipherBytes.byteOffset,\n cipherBytes.byteOffset + cipherBytes.byteLength\n ) as ArrayBuffer;\n\n const plainBuffer = await crypto.subtle.decrypt({ name: ALGO, iv }, key, cipherBuffer);\n\n return getTextDecoder().decode(plainBuffer);\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction bufferToBase64(buffer: Uint8Array): string {\n return btoa(String.fromCharCode(...buffer))\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\nfunction base64ToBuffer(b64: string): Uint8Array {\n const padded = b64.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const binary = atob(padded);\n return Uint8Array.from(binary, (c) => c.charCodeAt(0));\n}\n","import type { AuthConfig, AuthTokens } from \"../types\";\nimport { encrypt, decrypt } from \"../utils/crypto\";\n\n/**\n * Manages storage, retrieval, and expiry checks for auth tokens.\n * Supports \"cookie\" and \"memory\" storage strategies.\n */\nexport class TokenManager {\n private memoryStore: AuthTokens | null = null;\n private readonly config: AuthConfig;\n\n constructor(config: AuthConfig) {\n this.config = config;\n }\n\n // ─── Public API ─────────────────────────────────────────────────────────────\n\n getTokens(): AuthTokens | null {\n if (this.config.token.storage === \"memory\") {\n return this.memoryStore;\n }\n return this.readFromCookie();\n }\n\n async setTokens(tokens: AuthTokens): Promise<void> {\n if (this.config.token.storage === \"memory\") {\n this.memoryStore = tokens;\n return;\n }\n await this.writeToCookie(tokens);\n }\n\n clearTokens(): void {\n this.memoryStore = null;\n if (this.config.token.storage === \"cookie\") {\n this.deleteCookie();\n }\n }\n\n isAccessExpired(tokens: AuthTokens): boolean {\n const threshold = (this.config.refreshThreshold ?? 60) * 1000;\n return Date.now() >= tokens.accessTokenExpiresAt - threshold;\n }\n\n isRefreshExpired(tokens: AuthTokens): boolean {\n if (!tokens.refreshTokenExpiresAt) return false;\n return Date.now() >= tokens.refreshTokenExpiresAt;\n }\n\n // ─── Cookie helpers (client-side only) ──────────────────────────────────────\n\n private cookieName(): string {\n return this.config.token.cookieName ?? \"next-auth-kit.session\";\n }\n\n private readFromCookie(): AuthTokens | null {\n if (typeof document === \"undefined\") return null;\n\n const raw = getCookieValue(this.cookieName());\n if (!raw) return null;\n\n try {\n // Tokens are stored as JSON; encryption is applied server-side via\n // getServerSession. Client reads the plaintext access token from cookie.\n return JSON.parse(decodeURIComponent(raw)) as AuthTokens;\n } catch {\n return null;\n }\n }\n\n private async writeToCookie(tokens: AuthTokens): Promise<void> {\n if (typeof document === \"undefined\") return;\n\n const value = encodeURIComponent(JSON.stringify(tokens));\n const secure = this.config.token.secure !== false ? \"; Secure\" : \"\";\n const sameSite = this.config.token.sameSite ?? \"lax\";\n const maxAge = tokens.refreshTokenExpiresAt\n ? Math.floor((tokens.refreshTokenExpiresAt - Date.now()) / 1000)\n : 604800; // 7 days default\n\n document.cookie = [\n `${this.cookieName()}=${value}`,\n `Max-Age=${maxAge}`,\n `Path=/`,\n `SameSite=${sameSite}`,\n secure,\n ]\n .filter(Boolean)\n .join(\"; \");\n }\n\n private deleteCookie(): void {\n if (typeof document === \"undefined\") return;\n document.cookie = `${this.cookieName()}=; Max-Age=0; Path=/`;\n }\n\n // ─── Server-side helpers ─────────────────────────────────────────────────────\n\n /**\n * Encrypts tokens for secure server-side cookie storage.\n */\n async encryptTokens(tokens: AuthTokens): Promise<string> {\n return encrypt(JSON.stringify(tokens), this.config.secret);\n }\n\n /**\n * Decrypts tokens from a server-side cookie value.\n */\n async decryptTokens(ciphertext: string): Promise<AuthTokens | null> {\n try {\n const json = await decrypt(ciphertext, this.config.secret);\n return JSON.parse(json) as AuthTokens;\n } catch {\n return null;\n }\n }\n}\n\n// ─── Utility ──────────────────────────────────────────────────────────────────\n\nfunction getCookieValue(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n const match = document.cookie.match(\n new RegExp(`(?:^|;\\\\s*)${escapeRegex(name)}=([^;]*)`)\n );\n return match ? match[1] : null;\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import type {\n AuthConfig,\n AuthSession,\n AuthTokens,\n LoginInput,\n LoginResponse,\n} from \"../types\";\nimport { resolveAccessTokenExpiry, resolveRefreshTokenExpiry } from \"../utils/expiry\";\nimport { HttpClient } from \"./HttpClient\";\nimport { SessionManager } from \"./SessionManager\";\nimport { TokenManager } from \"./TokenManager\";\n\n/**\n * Central orchestrator for authentication operations.\n * Coordinates TokenManager, SessionManager, and HttpClient.\n */\nexport class AuthClient<User = unknown> {\n readonly tokenManager: TokenManager;\n readonly sessionManager: SessionManager<User>;\n readonly httpClient: HttpClient;\n\n private readonly config: AuthConfig<User>;\n private sessionListeners: Array<(session: AuthSession<User>) => void> = [];\n\n constructor(config: AuthConfig<User>) {\n this.config = config;\n this.tokenManager = new TokenManager(config as AuthConfig<unknown>);\n this.httpClient = new HttpClient(config as AuthConfig<unknown>, this.tokenManager);\n this.sessionManager = new SessionManager(\n config,\n this.tokenManager,\n this.httpClient\n );\n\n // Wire up the refresh callback\n this.httpClient.setRefreshFn(() => this.refresh());\n }\n\n // ─── Auth Operations ────────────────────────────────────────────────────────\n\n /**\n * Authenticates the user and stores tokens.\n */\n async login(input: LoginInput): Promise<AuthSession<User>> {\n const res = await this.httpClient.doFetch(\n this.httpClient.url(this.config.endpoints.login),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(input),\n }\n );\n\n if (!res.ok) {\n const error = await res.text();\n throw new Error(`Login failed (${res.status}): ${error}`);\n }\n\n const data = (await res.json()) as LoginResponse<User>;\n const tokens = this.buildTokens(data);\n\n await this.tokenManager.setTokens(tokens);\n await this.sessionManager.loadSession();\n\n const session = this.sessionManager.getSession();\n this.config.onLogin?.(session);\n this.notifyListeners(session);\n\n return session;\n }\n\n /**\n * Logs out the user, clears tokens, and optionally calls the backend.\n */\n async logout(): Promise<void> {\n const logoutEndpoint = this.config.endpoints.logout;\n\n if (logoutEndpoint) {\n try {\n await this.httpClient.fetch(this.httpClient.url(logoutEndpoint), {\n method: \"POST\",\n });\n } catch {\n // Best-effort logout\n }\n }\n\n this.tokenManager.clearTokens();\n this.sessionManager.clearSession();\n this.config.onLogout?.();\n this.notifyListeners(this.sessionManager.getSession());\n }\n\n /**\n * Refreshes the access token using the stored refresh token.\n * Returns true on success, false on failure.\n */\n async refresh(): Promise<boolean> {\n const tokens = this.tokenManager.getTokens();\n\n if (!tokens) return false;\n if (this.tokenManager.isRefreshExpired(tokens)) {\n await this.logout();\n return false;\n }\n\n try {\n const res = await this.httpClient.doFetch(\n this.httpClient.url(this.config.endpoints.refresh),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refreshToken: tokens.refreshToken }),\n }\n );\n\n if (!res.ok) {\n await this.logout();\n return false;\n }\n\n const data = (await res.json()) as LoginResponse<User>;\n const newTokens = this.buildTokens(data);\n\n await this.tokenManager.setTokens(newTokens);\n await this.sessionManager.refreshSession(newTokens);\n this.notifyListeners(this.sessionManager.getSession());\n\n return true;\n } catch (err) {\n this.config.onRefreshError?.(err);\n return false;\n }\n }\n\n /**\n * Loads the session from stored tokens (call on app mount).\n */\n async initialize(): Promise<AuthSession<User>> {\n const session = await this.sessionManager.loadSession();\n\n // Proactively refresh if access token is near expiry\n if (\n session.isAuthenticated &&\n session.tokens &&\n this.tokenManager.isAccessExpired(session.tokens) &&\n !this.tokenManager.isRefreshExpired(session.tokens)\n ) {\n await this.refresh();\n }\n\n return this.sessionManager.getSession();\n }\n\n getSession(): AuthSession<User> {\n return this.sessionManager.getSession();\n }\n\n /**\n * Returns the authenticated fetch wrapper.\n */\n get fetch(): HttpClient[\"fetch\"] {\n return this.httpClient.fetch.bind(this.httpClient);\n }\n\n // ─── Subscription ────────────────────────────────────────────────────────────\n\n subscribe(listener: (session: AuthSession<User>) => void): () => void {\n this.sessionListeners.push(listener);\n return () => {\n this.sessionListeners = this.sessionListeners.filter((l) => l !== listener);\n };\n }\n\n // ─── Private ────────────────────────────────────────────────────────────────\n\n private buildTokens(data: LoginResponse<User>): AuthTokens {\n const strategy = this.config.expiry?.strategy ?? \"hybrid\";\n const configAccess = this.config.expiry?.accessTokenExpiresIn;\n const configRefresh = this.config.expiry?.refreshTokenExpiresIn;\n\n return {\n accessToken: data.accessToken,\n refreshToken: data.refreshToken,\n accessTokenExpiresAt: resolveAccessTokenExpiry(data, configAccess, strategy),\n refreshTokenExpiresAt: resolveRefreshTokenExpiry(data, configRefresh, strategy),\n };\n }\n\n private notifyListeners(session: AuthSession<User>): void {\n for (const listener of this.sessionListeners) {\n listener(session);\n }\n }\n}\n","\"use client\";\n\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { AuthClient } from \"../core/AuthClient\";\nimport type { AuthConfig, AuthSession, LoginInput } from \"../types\";\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\ninterface AuthContextValue<User = unknown> {\n session: AuthSession<User>;\n isLoading: boolean;\n login: (input: LoginInput) => Promise<void>;\n logout: () => Promise<void>;\n refresh: () => Promise<void>;\n /** The underlying AuthClient for advanced use cases */\n client: AuthClient<User>;\n}\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\n// ─── Provider ─────────────────────────────────────────────────────────────────\n\ninterface AuthProviderProps<User = unknown> {\n config: AuthConfig<User>;\n children: React.ReactNode;\n}\n\nexport function AuthProvider<User = unknown>({\n config,\n children,\n}: AuthProviderProps<User>) {\n const clientRef = useRef<AuthClient<User> | null>(null);\n\n if (!clientRef.current) {\n clientRef.current = new AuthClient<User>(config);\n }\n\n const client = clientRef.current;\n\n const [session, setSession] = useState<AuthSession<User>>({\n user: null,\n tokens: null,\n isAuthenticated: false,\n });\n const [isLoading, setIsLoading] = useState(true);\n\n // Initialize session on mount\n useEffect(() => {\n let cancelled = false;\n\n client.initialize().then((s) => {\n if (!cancelled) {\n setSession(s);\n setIsLoading(false);\n }\n });\n\n // Subscribe to session changes\n const unsubscribe = client.subscribe((s) => {\n if (!cancelled) setSession(s);\n });\n\n return () => {\n cancelled = true;\n unsubscribe();\n };\n }, [client]);\n\n // Auto-refresh timer\n useEffect(() => {\n if (!config.autoRefresh) return;\n\n const interval = setInterval(async () => {\n const tokens = client.tokenManager.getTokens();\n if (\n tokens &&\n client.tokenManager.isAccessExpired(tokens) &&\n !client.tokenManager.isRefreshExpired(tokens)\n ) {\n await client.refresh();\n }\n }, 30_000); // check every 30s\n\n return () => clearInterval(interval);\n }, [client, config.autoRefresh]);\n\n const login = useCallback(\n async (input: LoginInput) => {\n setIsLoading(true);\n try {\n const s = await client.login(input);\n setSession(s);\n } finally {\n setIsLoading(false);\n }\n },\n [client]\n );\n\n const logout = useCallback(async () => {\n await client.logout();\n setSession({ user: null, tokens: null, isAuthenticated: false });\n }, [client]);\n\n const refresh = useCallback(async () => {\n await client.refresh();\n setSession(client.getSession());\n }, [client]);\n\n const value: AuthContextValue<User> = {\n session,\n isLoading,\n login,\n logout,\n refresh,\n client,\n };\n\n return (\n <AuthContext.Provider value={value as AuthContextValue}>\n {children}\n </AuthContext.Provider>\n );\n}\n\n// ─── Internal hook ────────────────────────────────────────────────────────────\n\nexport function useAuthContext<User = unknown>(): AuthContextValue<User> {\n const ctx = useContext(AuthContext);\n if (!ctx) {\n throw new Error(\"useAuthContext must be used within <AuthProvider>\");\n }\n return ctx as AuthContextValue<User>;\n}\n","\"use client\";\n\nimport type { AuthSession, LoginInput } from \"../../types\";\nimport { useAuthContext } from \"../AuthProvider\";\n\nexport interface UseAuthReturn<User = unknown> {\n session: AuthSession<User>;\n login: (input: LoginInput) => Promise<void>;\n logout: () => Promise<void>;\n refresh: () => Promise<void>;\n isLoading: boolean;\n}\n\n/**\n * Primary hook for authentication operations.\n *\n * @example\n * const { session, login, logout, isLoading } = useAuth();\n */\nexport function useAuth<User = unknown>(): UseAuthReturn<User> {\n const { session, login, logout, refresh, isLoading } =\n useAuthContext<User>();\n\n return { session, login, logout, refresh, isLoading };\n}\n","\"use client\";\n\nimport type { AuthSession } from \"../../types\";\nimport { useAuthContext } from \"../AuthProvider\";\n\n/**\n * Returns the current auth session without exposing login/logout actions.\n *\n * @example\n * const { user, isAuthenticated } = useSession();\n */\nexport function useSession<User = unknown>(): AuthSession<User> {\n return useAuthContext<User>().session;\n}\n","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { useAuthContext } from \"../AuthProvider\";\n\nexport interface UseRequireAuthOptions {\n /** Path to redirect unauthenticated users to. @default \"/login\" */\n redirectTo?: string;\n /** Called when the user is not authenticated (use for custom redirect logic) */\n onUnauthenticated?: () => void;\n}\n\n/**\n * Redirects unauthenticated users to the login page.\n * Works with both Next.js App Router and Pages Router.\n *\n * @example\n * // App Router (client component)\n * useRequireAuth({ redirectTo: \"/login\" });\n *\n * @example\n * // Custom handler\n * useRequireAuth({ onUnauthenticated: () => router.push(\"/login\") });\n */\nexport function useRequireAuth(options: UseRequireAuthOptions = {}): void {\n const { redirectTo = \"/login\", onUnauthenticated } = options;\n const { session, isLoading } = useAuthContext();\n\n useEffect(() => {\n if (isLoading) return;\n if (session.isAuthenticated) return;\n\n if (onUnauthenticated) {\n onUnauthenticated();\n return;\n }\n\n // Works in both App Router and Pages Router environments\n if (typeof window !== \"undefined\") {\n window.location.href = redirectTo;\n }\n }, [session.isAuthenticated, isLoading, redirectTo, onUnauthenticated]);\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/expiry.ts","../src/core/HttpClient.ts","../src/core/SessionManager.ts","../src/utils/crypto.ts","../src/core/TokenManager.ts","../src/core/AuthClient.ts","../src/react/AuthProvider.tsx","../src/react/hooks/useAuth.ts","../src/react/hooks/useSession.ts","../src/react/hooks/useRequireAuth.ts"],"names":["createContext","useRef","useState","useEffect","useCallback","jsx","useContext"],"mappings":"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","file":"index.js","sourcesContent":["import type { ExpiryInput, ExpiryStrategy, LoginResponse } from \"../types\";\n\nconst UNIT_MAP: Record<string, number> = {\n s: 1,\n m: 60,\n h: 3600,\n d: 86400,\n w: 604800,\n};\n\n/**\n * Parses an expiry value into seconds.\n * Accepts:\n * - number → treated as seconds\n * - string → e.g. \"15m\", \"2h\", \"2d\", \"7d\", \"1w\"\n *\n * @throws if the format is unrecognised\n */\nexport function parseExpiry(input?: ExpiryInput): number {\n if (input === undefined || input === null) {\n throw new Error(\"parseExpiry: no expiry value provided\");\n }\n\n if (typeof input === \"number\") {\n if (input <= 0) throw new Error(\"parseExpiry: value must be positive\");\n return input;\n }\n\n const trimmed = input.trim();\n\n // Pure numeric string\n if (/^\\d+$/.test(trimmed)) {\n return parseInt(trimmed, 10);\n }\n\n const match = trimmed.match(/^(\\d+(?:\\.\\d+)?)\\s*([smhdw])$/i);\n if (!match) {\n throw new Error(\n `parseExpiry: unrecognised format \"${input}\". ` +\n `Expected a number or a string like \"15m\", \"2h\", \"2d\", \"7d\", \"1w\".`\n );\n }\n\n const value = parseFloat(match[1]);\n const unit = match[2].toLowerCase();\n return Math.floor(value * UNIT_MAP[unit]);\n}\n\n/**\n * Safely parses an expiry value, returning a fallback on failure.\n */\nexport function safeParseExpiry(\n input?: ExpiryInput,\n fallbackSeconds = 900\n): number {\n try {\n return parseExpiry(input);\n } catch {\n return fallbackSeconds;\n }\n}\n\n/**\n * Resolves the access token expiry timestamp (ms) from a login response\n * using the configured strategy.\n */\nexport function resolveAccessTokenExpiry(\n response: LoginResponse,\n configExpiry?: ExpiryInput,\n strategy: ExpiryStrategy = \"hybrid\"\n): number {\n const now = Date.now();\n\n const fromBackend =\n response.accessTokenExpiresIn ?? response.expiresIn ?? undefined;\n\n if (strategy === \"backend\") {\n if (fromBackend === undefined) {\n throw new Error(\n 'resolveAccessTokenExpiry: strategy is \"backend\" but API returned no expiry'\n );\n }\n return now + parseExpiry(fromBackend) * 1000;\n }\n\n if (strategy === \"config\") {\n if (configExpiry === undefined) {\n throw new Error(\n 'resolveAccessTokenExpiry: strategy is \"config\" but no expiry configured'\n );\n }\n return now + parseExpiry(configExpiry) * 1000;\n }\n\n // hybrid: backend first, fallback to config\n if (fromBackend !== undefined) {\n return now + safeParseExpiry(fromBackend) * 1000;\n }\n if (configExpiry !== undefined) {\n return now + safeParseExpiry(configExpiry) * 1000;\n }\n\n // Last resort: 15 minutes\n return now + 900 * 1000;\n}\n\n/**\n * Resolves the refresh token expiry timestamp (ms).\n */\nexport function resolveRefreshTokenExpiry(\n response: LoginResponse,\n configExpiry?: ExpiryInput,\n strategy: ExpiryStrategy = \"hybrid\"\n): number | undefined {\n const now = Date.now();\n const fromBackend = response.refreshTokenExpiresIn;\n\n if (strategy === \"backend\") {\n return fromBackend !== undefined\n ? now + parseExpiry(fromBackend) * 1000\n : undefined;\n }\n\n if (strategy === \"config\") {\n return configExpiry !== undefined\n ? now + parseExpiry(configExpiry) * 1000\n : undefined;\n }\n\n // hybrid\n if (fromBackend !== undefined) {\n return now + safeParseExpiry(fromBackend) * 1000;\n }\n if (configExpiry !== undefined) {\n return now + safeParseExpiry(configExpiry) * 1000;\n }\n\n return undefined;\n}\n","import type { AuthConfig } from \"../types\";\nimport type { TokenManager } from \"./TokenManager\";\n\ntype RefreshFn = () => Promise<boolean>;\n\n/**\n * Authenticated HTTP client that:\n * - Injects Authorization: Bearer <accessToken>\n * - Auto-refreshes on 401 and retries the original request once\n */\nexport class HttpClient {\n private readonly config: AuthConfig;\n private readonly tokenManager: TokenManager;\n private refreshFn: RefreshFn | null = null;\n private refreshPromise: Promise<boolean> | null = null;\n\n constructor(config: AuthConfig, tokenManager: TokenManager) {\n this.config = config;\n this.tokenManager = tokenManager;\n }\n\n /** Register the refresh callback (set by AuthClient to avoid circular deps) */\n setRefreshFn(fn: RefreshFn): void {\n this.refreshFn = fn;\n }\n\n /**\n * Authenticated fetch wrapper.\n * Automatically injects the Bearer token and handles 401 → refresh → retry.\n */\n async fetch(input: RequestInfo | URL, init: RequestInit = {}): Promise<Response> {\n const tokens = this.tokenManager.getTokens();\n\n const headers = new Headers(init.headers);\n if (tokens?.accessToken) {\n headers.set(\"Authorization\", `Bearer ${tokens.accessToken}`);\n }\n\n const response = await this.doFetch(input, { ...init, headers });\n\n if (response.status === 401 && this.refreshFn) {\n const refreshed = await this.deduplicatedRefresh();\n if (refreshed) {\n // Retry with new token\n const newTokens = this.tokenManager.getTokens();\n if (newTokens?.accessToken) {\n headers.set(\"Authorization\", `Bearer ${newTokens.accessToken}`);\n }\n return this.doFetch(input, { ...init, headers });\n }\n }\n\n return response;\n }\n\n /**\n * Raw fetch using the configured fetchFn or global fetch.\n */\n async doFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n const fetchFn = this.config.fetchFn ?? fetch;\n return fetchFn(input as RequestInfo, init);\n }\n\n /**\n * Builds a full URL from a path relative to baseUrl.\n */\n url(path: string): string {\n return `${this.config.baseUrl.replace(/\\/$/, \"\")}/${path.replace(/^\\//, \"\")}`;\n }\n\n // ─── Private ────────────────────────────────────────────────────────────────\n\n /**\n * Ensures only one refresh request is in-flight at a time.\n */\n private async deduplicatedRefresh(): Promise<boolean> {\n if (this.refreshPromise) return this.refreshPromise;\n\n this.refreshPromise = this.refreshFn!().finally(() => {\n this.refreshPromise = null;\n });\n\n return this.refreshPromise;\n }\n}\n","import type { AuthConfig, AuthSession, AuthTokens } from \"../types\";\nimport type { HttpClient } from \"./HttpClient\";\nimport type { TokenManager } from \"./TokenManager\";\n\n/**\n * Derives and caches the current AuthSession from stored tokens.\n * Fetches the user profile from the /me endpoint when available.\n */\nexport class SessionManager<User = unknown> {\n private session: AuthSession<User> = {\n user: null,\n tokens: null,\n isAuthenticated: false,\n };\n\n private readonly config: AuthConfig<User>;\n private readonly tokenManager: TokenManager;\n private readonly httpClient: HttpClient;\n\n constructor(\n config: AuthConfig<User>,\n tokenManager: TokenManager,\n httpClient: HttpClient\n ) {\n this.config = config;\n this.tokenManager = tokenManager;\n this.httpClient = httpClient;\n }\n\n getSession(): AuthSession<User> {\n return this.session;\n }\n\n setSession(session: AuthSession<User>): void {\n this.session = session;\n }\n\n /**\n * Builds a session from stored tokens, optionally fetching the user profile.\n */\n async loadSession(): Promise<AuthSession<User>> {\n const tokens = this.tokenManager.getTokens();\n\n if (!tokens) {\n this.session = { user: null, tokens: null, isAuthenticated: false };\n return this.session;\n }\n\n // If access token is expired and refresh is also expired, clear everything\n if (\n this.tokenManager.isAccessExpired(tokens) &&\n this.tokenManager.isRefreshExpired(tokens)\n ) {\n this.tokenManager.clearTokens();\n this.session = { user: null, tokens: null, isAuthenticated: false };\n return this.session;\n }\n\n const user = await this.fetchUser(tokens);\n this.session = {\n user,\n tokens,\n isAuthenticated: true,\n };\n\n return this.session;\n }\n\n /**\n * Updates the session after a successful token refresh.\n */\n async refreshSession(tokens: AuthTokens): Promise<void> {\n const user = this.session.user ?? (await this.fetchUser(tokens));\n this.session = { user, tokens, isAuthenticated: true };\n }\n\n clearSession(): void {\n this.session = { user: null, tokens: null, isAuthenticated: false };\n }\n\n // ─── Private ────────────────────────────────────────────────────────────────\n\n private async fetchUser(tokens: AuthTokens): Promise<User | null> {\n const meEndpoint = this.config.endpoints.me;\n if (!meEndpoint) return null;\n\n try {\n const res = await this.httpClient.fetch(this.httpClient.url(meEndpoint));\n if (!res.ok) return null;\n return (await res.json()) as User;\n } catch {\n return null;\n }\n }\n}\n","/**\n * Lightweight symmetric encryption using AES-GCM via the Web Crypto API.\n * Works in both browser and Node.js (>=18) / Edge runtimes.\n */\n\nconst ALGO = \"AES-GCM\";\nconst IV_LENGTH = 12; // bytes\n\nfunction getTextEncoder() {\n return new TextEncoder();\n}\n\nfunction getTextDecoder() {\n return new TextDecoder();\n}\n\nasync function deriveKey(secret: string): Promise<CryptoKey> {\n const raw = getTextEncoder().encode(secret.padEnd(32, \"0\").slice(0, 32));\n return crypto.subtle.importKey(\"raw\", raw, { name: ALGO }, false, [\n \"encrypt\",\n \"decrypt\",\n ]);\n}\n\n/**\n * Encrypts a plaintext string using AES-GCM.\n * Returns a base64url-encoded string: `<iv>.<ciphertext>`\n */\nexport async function encrypt(data: string, secret: string): Promise<string> {\n const key = await deriveKey(secret);\n const ivArray = crypto.getRandomValues(new Uint8Array(IV_LENGTH));\n // Ensure we have a plain ArrayBuffer for SubtleCrypto\n const iv = ivArray.buffer.slice(0, IV_LENGTH) as ArrayBuffer;\n const encoded = getTextEncoder().encode(data);\n\n const cipherBuffer = await crypto.subtle.encrypt({ name: ALGO, iv }, key, encoded);\n\n const ivB64 = bufferToBase64(new Uint8Array(iv));\n const cipherB64 = bufferToBase64(new Uint8Array(cipherBuffer));\n return `${ivB64}.${cipherB64}`;\n}\n\n/**\n * Decrypts a string produced by `encrypt`.\n */\nexport async function decrypt(data: string, secret: string): Promise<string> {\n const [ivB64, cipherB64] = data.split(\".\");\n if (!ivB64 || !cipherB64) {\n throw new Error(\"decrypt: invalid ciphertext format\");\n }\n\n const key = await deriveKey(secret);\n const ivBytes = base64ToBuffer(ivB64);\n const iv = ivBytes.buffer.slice(\n ivBytes.byteOffset,\n ivBytes.byteOffset + ivBytes.byteLength\n ) as ArrayBuffer;\n\n const cipherBytes = base64ToBuffer(cipherB64);\n const cipherBuffer = cipherBytes.buffer.slice(\n cipherBytes.byteOffset,\n cipherBytes.byteOffset + cipherBytes.byteLength\n ) as ArrayBuffer;\n\n const plainBuffer = await crypto.subtle.decrypt({ name: ALGO, iv }, key, cipherBuffer);\n\n return getTextDecoder().decode(plainBuffer);\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction bufferToBase64(buffer: Uint8Array): string {\n return btoa(String.fromCharCode(...buffer))\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\nfunction base64ToBuffer(b64: string): Uint8Array {\n const padded = b64.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const binary = atob(padded);\n return Uint8Array.from(binary, (c) => c.charCodeAt(0));\n}\n","import type { AuthConfig, AuthTokens } from \"../types\";\nimport { encrypt, decrypt } from \"../utils/crypto\";\n\n/**\n * Manages storage, retrieval, and expiry checks for auth tokens.\n * Supports \"cookie\" and \"memory\" storage strategies.\n */\nexport class TokenManager {\n private memoryStore: AuthTokens | null = null;\n private readonly config: AuthConfig;\n\n constructor(config: AuthConfig) {\n this.config = config;\n }\n\n // ─── Public API ─────────────────────────────────────────────────────────────\n\n getTokens(): AuthTokens | null {\n if (this.config.token.storage === \"memory\") {\n return this.memoryStore;\n }\n return this.readFromCookie();\n }\n\n async setTokens(tokens: AuthTokens): Promise<void> {\n if (this.config.token.storage === \"memory\") {\n this.memoryStore = tokens;\n return;\n }\n await this.writeToCookie(tokens);\n }\n\n clearTokens(): void {\n this.memoryStore = null;\n if (this.config.token.storage === \"cookie\") {\n this.deleteCookie();\n }\n }\n\n isAccessExpired(tokens: AuthTokens): boolean {\n const threshold = (this.config.refreshThreshold ?? 60) * 1000;\n return Date.now() >= tokens.accessTokenExpiresAt - threshold;\n }\n\n isRefreshExpired(tokens: AuthTokens): boolean {\n if (!tokens.refreshTokenExpiresAt) return false;\n return Date.now() >= tokens.refreshTokenExpiresAt;\n }\n\n // ─── Cookie helpers (client-side only) ──────────────────────────────────────\n\n private cookieName(): string {\n return this.config.token.cookieName ?? \"next-token-auth.session\";\n }\n\n private readFromCookie(): AuthTokens | null {\n if (typeof document === \"undefined\") return null;\n\n const raw = getCookieValue(this.cookieName());\n if (!raw) return null;\n\n try {\n // Tokens are stored as JSON; encryption is applied server-side via\n // getServerSession. Client reads the plaintext access token from cookie.\n return JSON.parse(decodeURIComponent(raw)) as AuthTokens;\n } catch {\n return null;\n }\n }\n\n private async writeToCookie(tokens: AuthTokens): Promise<void> {\n if (typeof document === \"undefined\") return;\n\n const value = encodeURIComponent(JSON.stringify(tokens));\n const secure = this.config.token.secure !== false ? \"; Secure\" : \"\";\n const sameSite = this.config.token.sameSite ?? \"lax\";\n const maxAge = tokens.refreshTokenExpiresAt\n ? Math.floor((tokens.refreshTokenExpiresAt - Date.now()) / 1000)\n : 604800; // 7 days default\n\n document.cookie = [\n `${this.cookieName()}=${value}`,\n `Max-Age=${maxAge}`,\n `Path=/`,\n `SameSite=${sameSite}`,\n secure,\n ]\n .filter(Boolean)\n .join(\"; \");\n }\n\n private deleteCookie(): void {\n if (typeof document === \"undefined\") return;\n document.cookie = `${this.cookieName()}=; Max-Age=0; Path=/`;\n }\n\n // ─── Server-side helpers ─────────────────────────────────────────────────────\n\n /**\n * Encrypts tokens for secure server-side cookie storage.\n */\n async encryptTokens(tokens: AuthTokens): Promise<string> {\n return encrypt(JSON.stringify(tokens), this.config.secret);\n }\n\n /**\n * Decrypts tokens from a server-side cookie value.\n */\n async decryptTokens(ciphertext: string): Promise<AuthTokens | null> {\n try {\n const json = await decrypt(ciphertext, this.config.secret);\n return JSON.parse(json) as AuthTokens;\n } catch {\n return null;\n }\n }\n}\n\n// ─── Utility ──────────────────────────────────────────────────────────────────\n\nfunction getCookieValue(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n const match = document.cookie.match(\n new RegExp(`(?:^|;\\\\s*)${escapeRegex(name)}=([^;]*)`)\n );\n return match ? match[1] : null;\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import type {\n AuthConfig,\n AuthSession,\n AuthTokens,\n LoginInput,\n LoginResponse,\n} from \"../types\";\nimport { resolveAccessTokenExpiry, resolveRefreshTokenExpiry } from \"../utils/expiry\";\nimport { HttpClient } from \"./HttpClient\";\nimport { SessionManager } from \"./SessionManager\";\nimport { TokenManager } from \"./TokenManager\";\n\n/**\n * Central orchestrator for authentication operations.\n * Coordinates TokenManager, SessionManager, and HttpClient.\n */\nexport class AuthClient<User = unknown> {\n readonly tokenManager: TokenManager;\n readonly sessionManager: SessionManager<User>;\n readonly httpClient: HttpClient;\n\n private readonly config: AuthConfig<User>;\n private sessionListeners: Array<(session: AuthSession<User>) => void> = [];\n\n constructor(config: AuthConfig<User>) {\n this.config = config;\n this.tokenManager = new TokenManager(config as AuthConfig<unknown>);\n this.httpClient = new HttpClient(config as AuthConfig<unknown>, this.tokenManager);\n this.sessionManager = new SessionManager(\n config,\n this.tokenManager,\n this.httpClient\n );\n\n // Wire up the refresh callback\n this.httpClient.setRefreshFn(() => this.refresh());\n }\n\n // ─── Auth Operations ────────────────────────────────────────────────────────\n\n /**\n * Authenticates the user and stores tokens.\n */\n async login(input: LoginInput): Promise<AuthSession<User>> {\n const res = await this.httpClient.doFetch(\n this.httpClient.url(this.config.endpoints.login),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(input),\n }\n );\n\n if (!res.ok) {\n const error = await res.text();\n throw new Error(`Login failed (${res.status}): ${error}`);\n }\n\n const data = (await res.json()) as LoginResponse<User>;\n const tokens = this.buildTokens(data);\n\n await this.tokenManager.setTokens(tokens);\n await this.sessionManager.loadSession();\n\n const session = this.sessionManager.getSession();\n this.config.onLogin?.(session);\n this.notifyListeners(session);\n\n return session;\n }\n\n /**\n * Logs out the user, clears tokens, and optionally calls the backend.\n */\n async logout(): Promise<void> {\n const logoutEndpoint = this.config.endpoints.logout;\n\n if (logoutEndpoint) {\n try {\n await this.httpClient.fetch(this.httpClient.url(logoutEndpoint), {\n method: \"POST\",\n });\n } catch {\n // Best-effort logout\n }\n }\n\n this.tokenManager.clearTokens();\n this.sessionManager.clearSession();\n this.config.onLogout?.();\n this.notifyListeners(this.sessionManager.getSession());\n }\n\n /**\n * Refreshes the access token using the stored refresh token.\n * Returns true on success, false on failure.\n */\n async refresh(): Promise<boolean> {\n const tokens = this.tokenManager.getTokens();\n\n if (!tokens) return false;\n if (this.tokenManager.isRefreshExpired(tokens)) {\n await this.logout();\n return false;\n }\n\n try {\n const res = await this.httpClient.doFetch(\n this.httpClient.url(this.config.endpoints.refresh),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refreshToken: tokens.refreshToken }),\n }\n );\n\n if (!res.ok) {\n await this.logout();\n return false;\n }\n\n const data = (await res.json()) as LoginResponse<User>;\n const newTokens = this.buildTokens(data);\n\n await this.tokenManager.setTokens(newTokens);\n await this.sessionManager.refreshSession(newTokens);\n this.notifyListeners(this.sessionManager.getSession());\n\n return true;\n } catch (err) {\n this.config.onRefreshError?.(err);\n return false;\n }\n }\n\n /**\n * Loads the session from stored tokens (call on app mount).\n */\n async initialize(): Promise<AuthSession<User>> {\n const session = await this.sessionManager.loadSession();\n\n // Proactively refresh if access token is near expiry\n if (\n session.isAuthenticated &&\n session.tokens &&\n this.tokenManager.isAccessExpired(session.tokens) &&\n !this.tokenManager.isRefreshExpired(session.tokens)\n ) {\n await this.refresh();\n }\n\n return this.sessionManager.getSession();\n }\n\n getSession(): AuthSession<User> {\n return this.sessionManager.getSession();\n }\n\n /**\n * Returns the authenticated fetch wrapper.\n */\n get fetch(): HttpClient[\"fetch\"] {\n return this.httpClient.fetch.bind(this.httpClient);\n }\n\n // ─── Subscription ────────────────────────────────────────────────────────────\n\n subscribe(listener: (session: AuthSession<User>) => void): () => void {\n this.sessionListeners.push(listener);\n return () => {\n this.sessionListeners = this.sessionListeners.filter((l) => l !== listener);\n };\n }\n\n // ─── Private ────────────────────────────────────────────────────────────────\n\n private buildTokens(data: LoginResponse<User>): AuthTokens {\n const strategy = this.config.expiry?.strategy ?? \"hybrid\";\n const configAccess = this.config.expiry?.accessTokenExpiresIn;\n const configRefresh = this.config.expiry?.refreshTokenExpiresIn;\n\n return {\n accessToken: data.accessToken,\n refreshToken: data.refreshToken,\n accessTokenExpiresAt: resolveAccessTokenExpiry(data, configAccess, strategy),\n refreshTokenExpiresAt: resolveRefreshTokenExpiry(data, configRefresh, strategy),\n };\n }\n\n private notifyListeners(session: AuthSession<User>): void {\n for (const listener of this.sessionListeners) {\n listener(session);\n }\n }\n}\n","\"use client\";\n\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { AuthClient } from \"../core/AuthClient\";\nimport type { AuthConfig, AuthSession, LoginInput } from \"../types\";\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\ninterface AuthContextValue<User = unknown> {\n session: AuthSession<User>;\n isLoading: boolean;\n login: (input: LoginInput) => Promise<void>;\n logout: () => Promise<void>;\n refresh: () => Promise<void>;\n /** The underlying AuthClient for advanced use cases */\n client: AuthClient<User>;\n}\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\n// ─── Provider ─────────────────────────────────────────────────────────────────\n\ninterface AuthProviderProps<User = unknown> {\n config: AuthConfig<User>;\n children: React.ReactNode;\n}\n\nexport function AuthProvider<User = unknown>({\n config,\n children,\n}: AuthProviderProps<User>) {\n const clientRef = useRef<AuthClient<User> | null>(null);\n\n if (!clientRef.current) {\n clientRef.current = new AuthClient<User>(config);\n }\n\n const client = clientRef.current;\n\n const [session, setSession] = useState<AuthSession<User>>({\n user: null,\n tokens: null,\n isAuthenticated: false,\n });\n const [isLoading, setIsLoading] = useState(true);\n\n // Initialize session on mount\n useEffect(() => {\n let cancelled = false;\n\n client.initialize().then((s) => {\n if (!cancelled) {\n setSession(s);\n setIsLoading(false);\n }\n });\n\n // Subscribe to session changes\n const unsubscribe = client.subscribe((s) => {\n if (!cancelled) setSession(s);\n });\n\n return () => {\n cancelled = true;\n unsubscribe();\n };\n }, [client]);\n\n // Auto-refresh timer\n useEffect(() => {\n if (!config.autoRefresh) return;\n\n const interval = setInterval(async () => {\n const tokens = client.tokenManager.getTokens();\n if (\n tokens &&\n client.tokenManager.isAccessExpired(tokens) &&\n !client.tokenManager.isRefreshExpired(tokens)\n ) {\n await client.refresh();\n }\n }, 30_000); // check every 30s\n\n return () => clearInterval(interval);\n }, [client, config.autoRefresh]);\n\n const login = useCallback(\n async (input: LoginInput) => {\n setIsLoading(true);\n try {\n const s = await client.login(input);\n setSession(s);\n } finally {\n setIsLoading(false);\n }\n },\n [client]\n );\n\n const logout = useCallback(async () => {\n await client.logout();\n setSession({ user: null, tokens: null, isAuthenticated: false });\n }, [client]);\n\n const refresh = useCallback(async () => {\n await client.refresh();\n setSession(client.getSession());\n }, [client]);\n\n const value: AuthContextValue<User> = {\n session,\n isLoading,\n login,\n logout,\n refresh,\n client,\n };\n\n return (\n <AuthContext.Provider value={value as AuthContextValue}>\n {children}\n </AuthContext.Provider>\n );\n}\n\n// ─── Internal hook ────────────────────────────────────────────────────────────\n\nexport function useAuthContext<User = unknown>(): AuthContextValue<User> {\n const ctx = useContext(AuthContext);\n if (!ctx) {\n throw new Error(\"useAuthContext must be used within <AuthProvider>\");\n }\n return ctx as AuthContextValue<User>;\n}\n","\"use client\";\n\nimport type { AuthSession, LoginInput } from \"../../types\";\nimport { useAuthContext } from \"../AuthProvider\";\n\nexport interface UseAuthReturn<User = unknown> {\n session: AuthSession<User>;\n login: (input: LoginInput) => Promise<void>;\n logout: () => Promise<void>;\n refresh: () => Promise<void>;\n isLoading: boolean;\n}\n\n/**\n * Primary hook for authentication operations.\n *\n * @example\n * const { session, login, logout, isLoading } = useAuth();\n */\nexport function useAuth<User = unknown>(): UseAuthReturn<User> {\n const { session, login, logout, refresh, isLoading } =\n useAuthContext<User>();\n\n return { session, login, logout, refresh, isLoading };\n}\n","\"use client\";\n\nimport type { AuthSession } from \"../../types\";\nimport { useAuthContext } from \"../AuthProvider\";\n\n/**\n * Returns the current auth session without exposing login/logout actions.\n *\n * @example\n * const { user, isAuthenticated } = useSession();\n */\nexport function useSession<User = unknown>(): AuthSession<User> {\n return useAuthContext<User>().session;\n}\n","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { useAuthContext } from \"../AuthProvider\";\n\nexport interface UseRequireAuthOptions {\n /** Path to redirect unauthenticated users to. @default \"/login\" */\n redirectTo?: string;\n /** Called when the user is not authenticated (use for custom redirect logic) */\n onUnauthenticated?: () => void;\n}\n\n/**\n * Redirects unauthenticated users to the login page.\n * Works with both Next.js App Router and Pages Router.\n *\n * @example\n * // App Router (client component)\n * useRequireAuth({ redirectTo: \"/login\" });\n *\n * @example\n * // Custom handler\n * useRequireAuth({ onUnauthenticated: () => router.push(\"/login\") });\n */\nexport function useRequireAuth(options: UseRequireAuthOptions = {}): void {\n const { redirectTo = \"/login\", onUnauthenticated } = options;\n const { session, isLoading } = useAuthContext();\n\n useEffect(() => {\n if (isLoading) return;\n if (session.isAuthenticated) return;\n\n if (onUnauthenticated) {\n onUnauthenticated();\n return;\n }\n\n // Works in both App Router and Pages Router environments\n if (typeof window !== \"undefined\") {\n window.location.href = redirectTo;\n }\n }, [session.isAuthenticated, isLoading, redirectTo, onUnauthenticated]);\n}\n"]}
package/dist/index.mjs CHANGED
@@ -298,7 +298,7 @@ var TokenManager = class {
298
298
  }
299
299
  // ─── Cookie helpers (client-side only) ──────────────────────────────────────
300
300
  cookieName() {
301
- return this.config.token.cookieName ?? "next-auth-kit.session";
301
+ return this.config.token.cookieName ?? "next-token-auth.session";
302
302
  }
303
303
  readFromCookie() {
304
304
  if (typeof document === "undefined") return null;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/expiry.ts","../src/core/HttpClient.ts","../src/core/SessionManager.ts","../src/utils/crypto.ts","../src/core/TokenManager.ts","../src/core/AuthClient.ts","../src/react/AuthProvider.tsx","../src/react/hooks/useAuth.ts","../src/react/hooks/useSession.ts","../src/react/hooks/useRequireAuth.ts"],"names":["useEffect"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { ExpiryInput, ExpiryStrategy, LoginResponse } from \"../types\";\n\nconst UNIT_MAP: Record<string, number> = {\n s: 1,\n m: 60,\n h: 3600,\n d: 86400,\n w: 604800,\n};\n\n/**\n * Parses an expiry value into seconds.\n * Accepts:\n * - number → treated as seconds\n * - string → e.g. \"15m\", \"2h\", \"2d\", \"7d\", \"1w\"\n *\n * @throws if the format is unrecognised\n */\nexport function parseExpiry(input?: ExpiryInput): number {\n if (input === undefined || input === null) {\n throw new Error(\"parseExpiry: no expiry value provided\");\n }\n\n if (typeof input === \"number\") {\n if (input <= 0) throw new Error(\"parseExpiry: value must be positive\");\n return input;\n }\n\n const trimmed = input.trim();\n\n // Pure numeric string\n if (/^\\d+$/.test(trimmed)) {\n return parseInt(trimmed, 10);\n }\n\n const match = trimmed.match(/^(\\d+(?:\\.\\d+)?)\\s*([smhdw])$/i);\n if (!match) {\n throw new Error(\n `parseExpiry: unrecognised format \"${input}\". ` +\n `Expected a number or a string like \"15m\", \"2h\", \"2d\", \"7d\", \"1w\".`\n );\n }\n\n const value = parseFloat(match[1]);\n const unit = match[2].toLowerCase();\n return Math.floor(value * UNIT_MAP[unit]);\n}\n\n/**\n * Safely parses an expiry value, returning a fallback on failure.\n */\nexport function safeParseExpiry(\n input?: ExpiryInput,\n fallbackSeconds = 900\n): number {\n try {\n return parseExpiry(input);\n } catch {\n return fallbackSeconds;\n }\n}\n\n/**\n * Resolves the access token expiry timestamp (ms) from a login response\n * using the configured strategy.\n */\nexport function resolveAccessTokenExpiry(\n response: LoginResponse,\n configExpiry?: ExpiryInput,\n strategy: ExpiryStrategy = \"hybrid\"\n): number {\n const now = Date.now();\n\n const fromBackend =\n response.accessTokenExpiresIn ?? response.expiresIn ?? undefined;\n\n if (strategy === \"backend\") {\n if (fromBackend === undefined) {\n throw new Error(\n 'resolveAccessTokenExpiry: strategy is \"backend\" but API returned no expiry'\n );\n }\n return now + parseExpiry(fromBackend) * 1000;\n }\n\n if (strategy === \"config\") {\n if (configExpiry === undefined) {\n throw new Error(\n 'resolveAccessTokenExpiry: strategy is \"config\" but no expiry configured'\n );\n }\n return now + parseExpiry(configExpiry) * 1000;\n }\n\n // hybrid: backend first, fallback to config\n if (fromBackend !== undefined) {\n return now + safeParseExpiry(fromBackend) * 1000;\n }\n if (configExpiry !== undefined) {\n return now + safeParseExpiry(configExpiry) * 1000;\n }\n\n // Last resort: 15 minutes\n return now + 900 * 1000;\n}\n\n/**\n * Resolves the refresh token expiry timestamp (ms).\n */\nexport function resolveRefreshTokenExpiry(\n response: LoginResponse,\n configExpiry?: ExpiryInput,\n strategy: ExpiryStrategy = \"hybrid\"\n): number | undefined {\n const now = Date.now();\n const fromBackend = response.refreshTokenExpiresIn;\n\n if (strategy === \"backend\") {\n return fromBackend !== undefined\n ? now + parseExpiry(fromBackend) * 1000\n : undefined;\n }\n\n if (strategy === \"config\") {\n return configExpiry !== undefined\n ? now + parseExpiry(configExpiry) * 1000\n : undefined;\n }\n\n // hybrid\n if (fromBackend !== undefined) {\n return now + safeParseExpiry(fromBackend) * 1000;\n }\n if (configExpiry !== undefined) {\n return now + safeParseExpiry(configExpiry) * 1000;\n }\n\n return undefined;\n}\n","import type { AuthConfig } from \"../types\";\nimport type { TokenManager } from \"./TokenManager\";\n\ntype RefreshFn = () => Promise<boolean>;\n\n/**\n * Authenticated HTTP client that:\n * - Injects Authorization: Bearer <accessToken>\n * - Auto-refreshes on 401 and retries the original request once\n */\nexport class HttpClient {\n private readonly config: AuthConfig;\n private readonly tokenManager: TokenManager;\n private refreshFn: RefreshFn | null = null;\n private refreshPromise: Promise<boolean> | null = null;\n\n constructor(config: AuthConfig, tokenManager: TokenManager) {\n this.config = config;\n this.tokenManager = tokenManager;\n }\n\n /** Register the refresh callback (set by AuthClient to avoid circular deps) */\n setRefreshFn(fn: RefreshFn): void {\n this.refreshFn = fn;\n }\n\n /**\n * Authenticated fetch wrapper.\n * Automatically injects the Bearer token and handles 401 → refresh → retry.\n */\n async fetch(input: RequestInfo | URL, init: RequestInit = {}): Promise<Response> {\n const tokens = this.tokenManager.getTokens();\n\n const headers = new Headers(init.headers);\n if (tokens?.accessToken) {\n headers.set(\"Authorization\", `Bearer ${tokens.accessToken}`);\n }\n\n const response = await this.doFetch(input, { ...init, headers });\n\n if (response.status === 401 && this.refreshFn) {\n const refreshed = await this.deduplicatedRefresh();\n if (refreshed) {\n // Retry with new token\n const newTokens = this.tokenManager.getTokens();\n if (newTokens?.accessToken) {\n headers.set(\"Authorization\", `Bearer ${newTokens.accessToken}`);\n }\n return this.doFetch(input, { ...init, headers });\n }\n }\n\n return response;\n }\n\n /**\n * Raw fetch using the configured fetchFn or global fetch.\n */\n async doFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n const fetchFn = this.config.fetchFn ?? fetch;\n return fetchFn(input as RequestInfo, init);\n }\n\n /**\n * Builds a full URL from a path relative to baseUrl.\n */\n url(path: string): string {\n return `${this.config.baseUrl.replace(/\\/$/, \"\")}/${path.replace(/^\\//, \"\")}`;\n }\n\n // ─── Private ────────────────────────────────────────────────────────────────\n\n /**\n * Ensures only one refresh request is in-flight at a time.\n */\n private async deduplicatedRefresh(): Promise<boolean> {\n if (this.refreshPromise) return this.refreshPromise;\n\n this.refreshPromise = this.refreshFn!().finally(() => {\n this.refreshPromise = null;\n });\n\n return this.refreshPromise;\n }\n}\n","import type { AuthConfig, AuthSession, AuthTokens } from \"../types\";\nimport type { HttpClient } from \"./HttpClient\";\nimport type { TokenManager } from \"./TokenManager\";\n\n/**\n * Derives and caches the current AuthSession from stored tokens.\n * Fetches the user profile from the /me endpoint when available.\n */\nexport class SessionManager<User = unknown> {\n private session: AuthSession<User> = {\n user: null,\n tokens: null,\n isAuthenticated: false,\n };\n\n private readonly config: AuthConfig<User>;\n private readonly tokenManager: TokenManager;\n private readonly httpClient: HttpClient;\n\n constructor(\n config: AuthConfig<User>,\n tokenManager: TokenManager,\n httpClient: HttpClient\n ) {\n this.config = config;\n this.tokenManager = tokenManager;\n this.httpClient = httpClient;\n }\n\n getSession(): AuthSession<User> {\n return this.session;\n }\n\n setSession(session: AuthSession<User>): void {\n this.session = session;\n }\n\n /**\n * Builds a session from stored tokens, optionally fetching the user profile.\n */\n async loadSession(): Promise<AuthSession<User>> {\n const tokens = this.tokenManager.getTokens();\n\n if (!tokens) {\n this.session = { user: null, tokens: null, isAuthenticated: false };\n return this.session;\n }\n\n // If access token is expired and refresh is also expired, clear everything\n if (\n this.tokenManager.isAccessExpired(tokens) &&\n this.tokenManager.isRefreshExpired(tokens)\n ) {\n this.tokenManager.clearTokens();\n this.session = { user: null, tokens: null, isAuthenticated: false };\n return this.session;\n }\n\n const user = await this.fetchUser(tokens);\n this.session = {\n user,\n tokens,\n isAuthenticated: true,\n };\n\n return this.session;\n }\n\n /**\n * Updates the session after a successful token refresh.\n */\n async refreshSession(tokens: AuthTokens): Promise<void> {\n const user = this.session.user ?? (await this.fetchUser(tokens));\n this.session = { user, tokens, isAuthenticated: true };\n }\n\n clearSession(): void {\n this.session = { user: null, tokens: null, isAuthenticated: false };\n }\n\n // ─── Private ────────────────────────────────────────────────────────────────\n\n private async fetchUser(tokens: AuthTokens): Promise<User | null> {\n const meEndpoint = this.config.endpoints.me;\n if (!meEndpoint) return null;\n\n try {\n const res = await this.httpClient.fetch(this.httpClient.url(meEndpoint));\n if (!res.ok) return null;\n return (await res.json()) as User;\n } catch {\n return null;\n }\n }\n}\n","/**\n * Lightweight symmetric encryption using AES-GCM via the Web Crypto API.\n * Works in both browser and Node.js (>=18) / Edge runtimes.\n */\n\nconst ALGO = \"AES-GCM\";\nconst IV_LENGTH = 12; // bytes\n\nfunction getTextEncoder() {\n return new TextEncoder();\n}\n\nfunction getTextDecoder() {\n return new TextDecoder();\n}\n\nasync function deriveKey(secret: string): Promise<CryptoKey> {\n const raw = getTextEncoder().encode(secret.padEnd(32, \"0\").slice(0, 32));\n return crypto.subtle.importKey(\"raw\", raw, { name: ALGO }, false, [\n \"encrypt\",\n \"decrypt\",\n ]);\n}\n\n/**\n * Encrypts a plaintext string using AES-GCM.\n * Returns a base64url-encoded string: `<iv>.<ciphertext>`\n */\nexport async function encrypt(data: string, secret: string): Promise<string> {\n const key = await deriveKey(secret);\n const ivArray = crypto.getRandomValues(new Uint8Array(IV_LENGTH));\n // Ensure we have a plain ArrayBuffer for SubtleCrypto\n const iv = ivArray.buffer.slice(0, IV_LENGTH) as ArrayBuffer;\n const encoded = getTextEncoder().encode(data);\n\n const cipherBuffer = await crypto.subtle.encrypt({ name: ALGO, iv }, key, encoded);\n\n const ivB64 = bufferToBase64(new Uint8Array(iv));\n const cipherB64 = bufferToBase64(new Uint8Array(cipherBuffer));\n return `${ivB64}.${cipherB64}`;\n}\n\n/**\n * Decrypts a string produced by `encrypt`.\n */\nexport async function decrypt(data: string, secret: string): Promise<string> {\n const [ivB64, cipherB64] = data.split(\".\");\n if (!ivB64 || !cipherB64) {\n throw new Error(\"decrypt: invalid ciphertext format\");\n }\n\n const key = await deriveKey(secret);\n const ivBytes = base64ToBuffer(ivB64);\n const iv = ivBytes.buffer.slice(\n ivBytes.byteOffset,\n ivBytes.byteOffset + ivBytes.byteLength\n ) as ArrayBuffer;\n\n const cipherBytes = base64ToBuffer(cipherB64);\n const cipherBuffer = cipherBytes.buffer.slice(\n cipherBytes.byteOffset,\n cipherBytes.byteOffset + cipherBytes.byteLength\n ) as ArrayBuffer;\n\n const plainBuffer = await crypto.subtle.decrypt({ name: ALGO, iv }, key, cipherBuffer);\n\n return getTextDecoder().decode(plainBuffer);\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction bufferToBase64(buffer: Uint8Array): string {\n return btoa(String.fromCharCode(...buffer))\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\nfunction base64ToBuffer(b64: string): Uint8Array {\n const padded = b64.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const binary = atob(padded);\n return Uint8Array.from(binary, (c) => c.charCodeAt(0));\n}\n","import type { AuthConfig, AuthTokens } from \"../types\";\nimport { encrypt, decrypt } from \"../utils/crypto\";\n\n/**\n * Manages storage, retrieval, and expiry checks for auth tokens.\n * Supports \"cookie\" and \"memory\" storage strategies.\n */\nexport class TokenManager {\n private memoryStore: AuthTokens | null = null;\n private readonly config: AuthConfig;\n\n constructor(config: AuthConfig) {\n this.config = config;\n }\n\n // ─── Public API ─────────────────────────────────────────────────────────────\n\n getTokens(): AuthTokens | null {\n if (this.config.token.storage === \"memory\") {\n return this.memoryStore;\n }\n return this.readFromCookie();\n }\n\n async setTokens(tokens: AuthTokens): Promise<void> {\n if (this.config.token.storage === \"memory\") {\n this.memoryStore = tokens;\n return;\n }\n await this.writeToCookie(tokens);\n }\n\n clearTokens(): void {\n this.memoryStore = null;\n if (this.config.token.storage === \"cookie\") {\n this.deleteCookie();\n }\n }\n\n isAccessExpired(tokens: AuthTokens): boolean {\n const threshold = (this.config.refreshThreshold ?? 60) * 1000;\n return Date.now() >= tokens.accessTokenExpiresAt - threshold;\n }\n\n isRefreshExpired(tokens: AuthTokens): boolean {\n if (!tokens.refreshTokenExpiresAt) return false;\n return Date.now() >= tokens.refreshTokenExpiresAt;\n }\n\n // ─── Cookie helpers (client-side only) ──────────────────────────────────────\n\n private cookieName(): string {\n return this.config.token.cookieName ?? \"next-auth-kit.session\";\n }\n\n private readFromCookie(): AuthTokens | null {\n if (typeof document === \"undefined\") return null;\n\n const raw = getCookieValue(this.cookieName());\n if (!raw) return null;\n\n try {\n // Tokens are stored as JSON; encryption is applied server-side via\n // getServerSession. Client reads the plaintext access token from cookie.\n return JSON.parse(decodeURIComponent(raw)) as AuthTokens;\n } catch {\n return null;\n }\n }\n\n private async writeToCookie(tokens: AuthTokens): Promise<void> {\n if (typeof document === \"undefined\") return;\n\n const value = encodeURIComponent(JSON.stringify(tokens));\n const secure = this.config.token.secure !== false ? \"; Secure\" : \"\";\n const sameSite = this.config.token.sameSite ?? \"lax\";\n const maxAge = tokens.refreshTokenExpiresAt\n ? Math.floor((tokens.refreshTokenExpiresAt - Date.now()) / 1000)\n : 604800; // 7 days default\n\n document.cookie = [\n `${this.cookieName()}=${value}`,\n `Max-Age=${maxAge}`,\n `Path=/`,\n `SameSite=${sameSite}`,\n secure,\n ]\n .filter(Boolean)\n .join(\"; \");\n }\n\n private deleteCookie(): void {\n if (typeof document === \"undefined\") return;\n document.cookie = `${this.cookieName()}=; Max-Age=0; Path=/`;\n }\n\n // ─── Server-side helpers ─────────────────────────────────────────────────────\n\n /**\n * Encrypts tokens for secure server-side cookie storage.\n */\n async encryptTokens(tokens: AuthTokens): Promise<string> {\n return encrypt(JSON.stringify(tokens), this.config.secret);\n }\n\n /**\n * Decrypts tokens from a server-side cookie value.\n */\n async decryptTokens(ciphertext: string): Promise<AuthTokens | null> {\n try {\n const json = await decrypt(ciphertext, this.config.secret);\n return JSON.parse(json) as AuthTokens;\n } catch {\n return null;\n }\n }\n}\n\n// ─── Utility ──────────────────────────────────────────────────────────────────\n\nfunction getCookieValue(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n const match = document.cookie.match(\n new RegExp(`(?:^|;\\\\s*)${escapeRegex(name)}=([^;]*)`)\n );\n return match ? match[1] : null;\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import type {\n AuthConfig,\n AuthSession,\n AuthTokens,\n LoginInput,\n LoginResponse,\n} from \"../types\";\nimport { resolveAccessTokenExpiry, resolveRefreshTokenExpiry } from \"../utils/expiry\";\nimport { HttpClient } from \"./HttpClient\";\nimport { SessionManager } from \"./SessionManager\";\nimport { TokenManager } from \"./TokenManager\";\n\n/**\n * Central orchestrator for authentication operations.\n * Coordinates TokenManager, SessionManager, and HttpClient.\n */\nexport class AuthClient<User = unknown> {\n readonly tokenManager: TokenManager;\n readonly sessionManager: SessionManager<User>;\n readonly httpClient: HttpClient;\n\n private readonly config: AuthConfig<User>;\n private sessionListeners: Array<(session: AuthSession<User>) => void> = [];\n\n constructor(config: AuthConfig<User>) {\n this.config = config;\n this.tokenManager = new TokenManager(config as AuthConfig<unknown>);\n this.httpClient = new HttpClient(config as AuthConfig<unknown>, this.tokenManager);\n this.sessionManager = new SessionManager(\n config,\n this.tokenManager,\n this.httpClient\n );\n\n // Wire up the refresh callback\n this.httpClient.setRefreshFn(() => this.refresh());\n }\n\n // ─── Auth Operations ────────────────────────────────────────────────────────\n\n /**\n * Authenticates the user and stores tokens.\n */\n async login(input: LoginInput): Promise<AuthSession<User>> {\n const res = await this.httpClient.doFetch(\n this.httpClient.url(this.config.endpoints.login),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(input),\n }\n );\n\n if (!res.ok) {\n const error = await res.text();\n throw new Error(`Login failed (${res.status}): ${error}`);\n }\n\n const data = (await res.json()) as LoginResponse<User>;\n const tokens = this.buildTokens(data);\n\n await this.tokenManager.setTokens(tokens);\n await this.sessionManager.loadSession();\n\n const session = this.sessionManager.getSession();\n this.config.onLogin?.(session);\n this.notifyListeners(session);\n\n return session;\n }\n\n /**\n * Logs out the user, clears tokens, and optionally calls the backend.\n */\n async logout(): Promise<void> {\n const logoutEndpoint = this.config.endpoints.logout;\n\n if (logoutEndpoint) {\n try {\n await this.httpClient.fetch(this.httpClient.url(logoutEndpoint), {\n method: \"POST\",\n });\n } catch {\n // Best-effort logout\n }\n }\n\n this.tokenManager.clearTokens();\n this.sessionManager.clearSession();\n this.config.onLogout?.();\n this.notifyListeners(this.sessionManager.getSession());\n }\n\n /**\n * Refreshes the access token using the stored refresh token.\n * Returns true on success, false on failure.\n */\n async refresh(): Promise<boolean> {\n const tokens = this.tokenManager.getTokens();\n\n if (!tokens) return false;\n if (this.tokenManager.isRefreshExpired(tokens)) {\n await this.logout();\n return false;\n }\n\n try {\n const res = await this.httpClient.doFetch(\n this.httpClient.url(this.config.endpoints.refresh),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refreshToken: tokens.refreshToken }),\n }\n );\n\n if (!res.ok) {\n await this.logout();\n return false;\n }\n\n const data = (await res.json()) as LoginResponse<User>;\n const newTokens = this.buildTokens(data);\n\n await this.tokenManager.setTokens(newTokens);\n await this.sessionManager.refreshSession(newTokens);\n this.notifyListeners(this.sessionManager.getSession());\n\n return true;\n } catch (err) {\n this.config.onRefreshError?.(err);\n return false;\n }\n }\n\n /**\n * Loads the session from stored tokens (call on app mount).\n */\n async initialize(): Promise<AuthSession<User>> {\n const session = await this.sessionManager.loadSession();\n\n // Proactively refresh if access token is near expiry\n if (\n session.isAuthenticated &&\n session.tokens &&\n this.tokenManager.isAccessExpired(session.tokens) &&\n !this.tokenManager.isRefreshExpired(session.tokens)\n ) {\n await this.refresh();\n }\n\n return this.sessionManager.getSession();\n }\n\n getSession(): AuthSession<User> {\n return this.sessionManager.getSession();\n }\n\n /**\n * Returns the authenticated fetch wrapper.\n */\n get fetch(): HttpClient[\"fetch\"] {\n return this.httpClient.fetch.bind(this.httpClient);\n }\n\n // ─── Subscription ────────────────────────────────────────────────────────────\n\n subscribe(listener: (session: AuthSession<User>) => void): () => void {\n this.sessionListeners.push(listener);\n return () => {\n this.sessionListeners = this.sessionListeners.filter((l) => l !== listener);\n };\n }\n\n // ─── Private ────────────────────────────────────────────────────────────────\n\n private buildTokens(data: LoginResponse<User>): AuthTokens {\n const strategy = this.config.expiry?.strategy ?? \"hybrid\";\n const configAccess = this.config.expiry?.accessTokenExpiresIn;\n const configRefresh = this.config.expiry?.refreshTokenExpiresIn;\n\n return {\n accessToken: data.accessToken,\n refreshToken: data.refreshToken,\n accessTokenExpiresAt: resolveAccessTokenExpiry(data, configAccess, strategy),\n refreshTokenExpiresAt: resolveRefreshTokenExpiry(data, configRefresh, strategy),\n };\n }\n\n private notifyListeners(session: AuthSession<User>): void {\n for (const listener of this.sessionListeners) {\n listener(session);\n }\n }\n}\n","\"use client\";\n\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { AuthClient } from \"../core/AuthClient\";\nimport type { AuthConfig, AuthSession, LoginInput } from \"../types\";\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\ninterface AuthContextValue<User = unknown> {\n session: AuthSession<User>;\n isLoading: boolean;\n login: (input: LoginInput) => Promise<void>;\n logout: () => Promise<void>;\n refresh: () => Promise<void>;\n /** The underlying AuthClient for advanced use cases */\n client: AuthClient<User>;\n}\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\n// ─── Provider ─────────────────────────────────────────────────────────────────\n\ninterface AuthProviderProps<User = unknown> {\n config: AuthConfig<User>;\n children: React.ReactNode;\n}\n\nexport function AuthProvider<User = unknown>({\n config,\n children,\n}: AuthProviderProps<User>) {\n const clientRef = useRef<AuthClient<User> | null>(null);\n\n if (!clientRef.current) {\n clientRef.current = new AuthClient<User>(config);\n }\n\n const client = clientRef.current;\n\n const [session, setSession] = useState<AuthSession<User>>({\n user: null,\n tokens: null,\n isAuthenticated: false,\n });\n const [isLoading, setIsLoading] = useState(true);\n\n // Initialize session on mount\n useEffect(() => {\n let cancelled = false;\n\n client.initialize().then((s) => {\n if (!cancelled) {\n setSession(s);\n setIsLoading(false);\n }\n });\n\n // Subscribe to session changes\n const unsubscribe = client.subscribe((s) => {\n if (!cancelled) setSession(s);\n });\n\n return () => {\n cancelled = true;\n unsubscribe();\n };\n }, [client]);\n\n // Auto-refresh timer\n useEffect(() => {\n if (!config.autoRefresh) return;\n\n const interval = setInterval(async () => {\n const tokens = client.tokenManager.getTokens();\n if (\n tokens &&\n client.tokenManager.isAccessExpired(tokens) &&\n !client.tokenManager.isRefreshExpired(tokens)\n ) {\n await client.refresh();\n }\n }, 30_000); // check every 30s\n\n return () => clearInterval(interval);\n }, [client, config.autoRefresh]);\n\n const login = useCallback(\n async (input: LoginInput) => {\n setIsLoading(true);\n try {\n const s = await client.login(input);\n setSession(s);\n } finally {\n setIsLoading(false);\n }\n },\n [client]\n );\n\n const logout = useCallback(async () => {\n await client.logout();\n setSession({ user: null, tokens: null, isAuthenticated: false });\n }, [client]);\n\n const refresh = useCallback(async () => {\n await client.refresh();\n setSession(client.getSession());\n }, [client]);\n\n const value: AuthContextValue<User> = {\n session,\n isLoading,\n login,\n logout,\n refresh,\n client,\n };\n\n return (\n <AuthContext.Provider value={value as AuthContextValue}>\n {children}\n </AuthContext.Provider>\n );\n}\n\n// ─── Internal hook ────────────────────────────────────────────────────────────\n\nexport function useAuthContext<User = unknown>(): AuthContextValue<User> {\n const ctx = useContext(AuthContext);\n if (!ctx) {\n throw new Error(\"useAuthContext must be used within <AuthProvider>\");\n }\n return ctx as AuthContextValue<User>;\n}\n","\"use client\";\n\nimport type { AuthSession, LoginInput } from \"../../types\";\nimport { useAuthContext } from \"../AuthProvider\";\n\nexport interface UseAuthReturn<User = unknown> {\n session: AuthSession<User>;\n login: (input: LoginInput) => Promise<void>;\n logout: () => Promise<void>;\n refresh: () => Promise<void>;\n isLoading: boolean;\n}\n\n/**\n * Primary hook for authentication operations.\n *\n * @example\n * const { session, login, logout, isLoading } = useAuth();\n */\nexport function useAuth<User = unknown>(): UseAuthReturn<User> {\n const { session, login, logout, refresh, isLoading } =\n useAuthContext<User>();\n\n return { session, login, logout, refresh, isLoading };\n}\n","\"use client\";\n\nimport type { AuthSession } from \"../../types\";\nimport { useAuthContext } from \"../AuthProvider\";\n\n/**\n * Returns the current auth session without exposing login/logout actions.\n *\n * @example\n * const { user, isAuthenticated } = useSession();\n */\nexport function useSession<User = unknown>(): AuthSession<User> {\n return useAuthContext<User>().session;\n}\n","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { useAuthContext } from \"../AuthProvider\";\n\nexport interface UseRequireAuthOptions {\n /** Path to redirect unauthenticated users to. @default \"/login\" */\n redirectTo?: string;\n /** Called when the user is not authenticated (use for custom redirect logic) */\n onUnauthenticated?: () => void;\n}\n\n/**\n * Redirects unauthenticated users to the login page.\n * Works with both Next.js App Router and Pages Router.\n *\n * @example\n * // App Router (client component)\n * useRequireAuth({ redirectTo: \"/login\" });\n *\n * @example\n * // Custom handler\n * useRequireAuth({ onUnauthenticated: () => router.push(\"/login\") });\n */\nexport function useRequireAuth(options: UseRequireAuthOptions = {}): void {\n const { redirectTo = \"/login\", onUnauthenticated } = options;\n const { session, isLoading } = useAuthContext();\n\n useEffect(() => {\n if (isLoading) return;\n if (session.isAuthenticated) return;\n\n if (onUnauthenticated) {\n onUnauthenticated();\n return;\n }\n\n // Works in both App Router and Pages Router environments\n if (typeof window !== \"undefined\") {\n window.location.href = redirectTo;\n }\n }, [session.isAuthenticated, isLoading, redirectTo, onUnauthenticated]);\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/expiry.ts","../src/core/HttpClient.ts","../src/core/SessionManager.ts","../src/utils/crypto.ts","../src/core/TokenManager.ts","../src/core/AuthClient.ts","../src/react/AuthProvider.tsx","../src/react/hooks/useAuth.ts","../src/react/hooks/useSession.ts","../src/react/hooks/useRequireAuth.ts"],"names":["useEffect"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { ExpiryInput, ExpiryStrategy, LoginResponse } from \"../types\";\n\nconst UNIT_MAP: Record<string, number> = {\n s: 1,\n m: 60,\n h: 3600,\n d: 86400,\n w: 604800,\n};\n\n/**\n * Parses an expiry value into seconds.\n * Accepts:\n * - number → treated as seconds\n * - string → e.g. \"15m\", \"2h\", \"2d\", \"7d\", \"1w\"\n *\n * @throws if the format is unrecognised\n */\nexport function parseExpiry(input?: ExpiryInput): number {\n if (input === undefined || input === null) {\n throw new Error(\"parseExpiry: no expiry value provided\");\n }\n\n if (typeof input === \"number\") {\n if (input <= 0) throw new Error(\"parseExpiry: value must be positive\");\n return input;\n }\n\n const trimmed = input.trim();\n\n // Pure numeric string\n if (/^\\d+$/.test(trimmed)) {\n return parseInt(trimmed, 10);\n }\n\n const match = trimmed.match(/^(\\d+(?:\\.\\d+)?)\\s*([smhdw])$/i);\n if (!match) {\n throw new Error(\n `parseExpiry: unrecognised format \"${input}\". ` +\n `Expected a number or a string like \"15m\", \"2h\", \"2d\", \"7d\", \"1w\".`\n );\n }\n\n const value = parseFloat(match[1]);\n const unit = match[2].toLowerCase();\n return Math.floor(value * UNIT_MAP[unit]);\n}\n\n/**\n * Safely parses an expiry value, returning a fallback on failure.\n */\nexport function safeParseExpiry(\n input?: ExpiryInput,\n fallbackSeconds = 900\n): number {\n try {\n return parseExpiry(input);\n } catch {\n return fallbackSeconds;\n }\n}\n\n/**\n * Resolves the access token expiry timestamp (ms) from a login response\n * using the configured strategy.\n */\nexport function resolveAccessTokenExpiry(\n response: LoginResponse,\n configExpiry?: ExpiryInput,\n strategy: ExpiryStrategy = \"hybrid\"\n): number {\n const now = Date.now();\n\n const fromBackend =\n response.accessTokenExpiresIn ?? response.expiresIn ?? undefined;\n\n if (strategy === \"backend\") {\n if (fromBackend === undefined) {\n throw new Error(\n 'resolveAccessTokenExpiry: strategy is \"backend\" but API returned no expiry'\n );\n }\n return now + parseExpiry(fromBackend) * 1000;\n }\n\n if (strategy === \"config\") {\n if (configExpiry === undefined) {\n throw new Error(\n 'resolveAccessTokenExpiry: strategy is \"config\" but no expiry configured'\n );\n }\n return now + parseExpiry(configExpiry) * 1000;\n }\n\n // hybrid: backend first, fallback to config\n if (fromBackend !== undefined) {\n return now + safeParseExpiry(fromBackend) * 1000;\n }\n if (configExpiry !== undefined) {\n return now + safeParseExpiry(configExpiry) * 1000;\n }\n\n // Last resort: 15 minutes\n return now + 900 * 1000;\n}\n\n/**\n * Resolves the refresh token expiry timestamp (ms).\n */\nexport function resolveRefreshTokenExpiry(\n response: LoginResponse,\n configExpiry?: ExpiryInput,\n strategy: ExpiryStrategy = \"hybrid\"\n): number | undefined {\n const now = Date.now();\n const fromBackend = response.refreshTokenExpiresIn;\n\n if (strategy === \"backend\") {\n return fromBackend !== undefined\n ? now + parseExpiry(fromBackend) * 1000\n : undefined;\n }\n\n if (strategy === \"config\") {\n return configExpiry !== undefined\n ? now + parseExpiry(configExpiry) * 1000\n : undefined;\n }\n\n // hybrid\n if (fromBackend !== undefined) {\n return now + safeParseExpiry(fromBackend) * 1000;\n }\n if (configExpiry !== undefined) {\n return now + safeParseExpiry(configExpiry) * 1000;\n }\n\n return undefined;\n}\n","import type { AuthConfig } from \"../types\";\nimport type { TokenManager } from \"./TokenManager\";\n\ntype RefreshFn = () => Promise<boolean>;\n\n/**\n * Authenticated HTTP client that:\n * - Injects Authorization: Bearer <accessToken>\n * - Auto-refreshes on 401 and retries the original request once\n */\nexport class HttpClient {\n private readonly config: AuthConfig;\n private readonly tokenManager: TokenManager;\n private refreshFn: RefreshFn | null = null;\n private refreshPromise: Promise<boolean> | null = null;\n\n constructor(config: AuthConfig, tokenManager: TokenManager) {\n this.config = config;\n this.tokenManager = tokenManager;\n }\n\n /** Register the refresh callback (set by AuthClient to avoid circular deps) */\n setRefreshFn(fn: RefreshFn): void {\n this.refreshFn = fn;\n }\n\n /**\n * Authenticated fetch wrapper.\n * Automatically injects the Bearer token and handles 401 → refresh → retry.\n */\n async fetch(input: RequestInfo | URL, init: RequestInit = {}): Promise<Response> {\n const tokens = this.tokenManager.getTokens();\n\n const headers = new Headers(init.headers);\n if (tokens?.accessToken) {\n headers.set(\"Authorization\", `Bearer ${tokens.accessToken}`);\n }\n\n const response = await this.doFetch(input, { ...init, headers });\n\n if (response.status === 401 && this.refreshFn) {\n const refreshed = await this.deduplicatedRefresh();\n if (refreshed) {\n // Retry with new token\n const newTokens = this.tokenManager.getTokens();\n if (newTokens?.accessToken) {\n headers.set(\"Authorization\", `Bearer ${newTokens.accessToken}`);\n }\n return this.doFetch(input, { ...init, headers });\n }\n }\n\n return response;\n }\n\n /**\n * Raw fetch using the configured fetchFn or global fetch.\n */\n async doFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n const fetchFn = this.config.fetchFn ?? fetch;\n return fetchFn(input as RequestInfo, init);\n }\n\n /**\n * Builds a full URL from a path relative to baseUrl.\n */\n url(path: string): string {\n return `${this.config.baseUrl.replace(/\\/$/, \"\")}/${path.replace(/^\\//, \"\")}`;\n }\n\n // ─── Private ────────────────────────────────────────────────────────────────\n\n /**\n * Ensures only one refresh request is in-flight at a time.\n */\n private async deduplicatedRefresh(): Promise<boolean> {\n if (this.refreshPromise) return this.refreshPromise;\n\n this.refreshPromise = this.refreshFn!().finally(() => {\n this.refreshPromise = null;\n });\n\n return this.refreshPromise;\n }\n}\n","import type { AuthConfig, AuthSession, AuthTokens } from \"../types\";\nimport type { HttpClient } from \"./HttpClient\";\nimport type { TokenManager } from \"./TokenManager\";\n\n/**\n * Derives and caches the current AuthSession from stored tokens.\n * Fetches the user profile from the /me endpoint when available.\n */\nexport class SessionManager<User = unknown> {\n private session: AuthSession<User> = {\n user: null,\n tokens: null,\n isAuthenticated: false,\n };\n\n private readonly config: AuthConfig<User>;\n private readonly tokenManager: TokenManager;\n private readonly httpClient: HttpClient;\n\n constructor(\n config: AuthConfig<User>,\n tokenManager: TokenManager,\n httpClient: HttpClient\n ) {\n this.config = config;\n this.tokenManager = tokenManager;\n this.httpClient = httpClient;\n }\n\n getSession(): AuthSession<User> {\n return this.session;\n }\n\n setSession(session: AuthSession<User>): void {\n this.session = session;\n }\n\n /**\n * Builds a session from stored tokens, optionally fetching the user profile.\n */\n async loadSession(): Promise<AuthSession<User>> {\n const tokens = this.tokenManager.getTokens();\n\n if (!tokens) {\n this.session = { user: null, tokens: null, isAuthenticated: false };\n return this.session;\n }\n\n // If access token is expired and refresh is also expired, clear everything\n if (\n this.tokenManager.isAccessExpired(tokens) &&\n this.tokenManager.isRefreshExpired(tokens)\n ) {\n this.tokenManager.clearTokens();\n this.session = { user: null, tokens: null, isAuthenticated: false };\n return this.session;\n }\n\n const user = await this.fetchUser(tokens);\n this.session = {\n user,\n tokens,\n isAuthenticated: true,\n };\n\n return this.session;\n }\n\n /**\n * Updates the session after a successful token refresh.\n */\n async refreshSession(tokens: AuthTokens): Promise<void> {\n const user = this.session.user ?? (await this.fetchUser(tokens));\n this.session = { user, tokens, isAuthenticated: true };\n }\n\n clearSession(): void {\n this.session = { user: null, tokens: null, isAuthenticated: false };\n }\n\n // ─── Private ────────────────────────────────────────────────────────────────\n\n private async fetchUser(tokens: AuthTokens): Promise<User | null> {\n const meEndpoint = this.config.endpoints.me;\n if (!meEndpoint) return null;\n\n try {\n const res = await this.httpClient.fetch(this.httpClient.url(meEndpoint));\n if (!res.ok) return null;\n return (await res.json()) as User;\n } catch {\n return null;\n }\n }\n}\n","/**\n * Lightweight symmetric encryption using AES-GCM via the Web Crypto API.\n * Works in both browser and Node.js (>=18) / Edge runtimes.\n */\n\nconst ALGO = \"AES-GCM\";\nconst IV_LENGTH = 12; // bytes\n\nfunction getTextEncoder() {\n return new TextEncoder();\n}\n\nfunction getTextDecoder() {\n return new TextDecoder();\n}\n\nasync function deriveKey(secret: string): Promise<CryptoKey> {\n const raw = getTextEncoder().encode(secret.padEnd(32, \"0\").slice(0, 32));\n return crypto.subtle.importKey(\"raw\", raw, { name: ALGO }, false, [\n \"encrypt\",\n \"decrypt\",\n ]);\n}\n\n/**\n * Encrypts a plaintext string using AES-GCM.\n * Returns a base64url-encoded string: `<iv>.<ciphertext>`\n */\nexport async function encrypt(data: string, secret: string): Promise<string> {\n const key = await deriveKey(secret);\n const ivArray = crypto.getRandomValues(new Uint8Array(IV_LENGTH));\n // Ensure we have a plain ArrayBuffer for SubtleCrypto\n const iv = ivArray.buffer.slice(0, IV_LENGTH) as ArrayBuffer;\n const encoded = getTextEncoder().encode(data);\n\n const cipherBuffer = await crypto.subtle.encrypt({ name: ALGO, iv }, key, encoded);\n\n const ivB64 = bufferToBase64(new Uint8Array(iv));\n const cipherB64 = bufferToBase64(new Uint8Array(cipherBuffer));\n return `${ivB64}.${cipherB64}`;\n}\n\n/**\n * Decrypts a string produced by `encrypt`.\n */\nexport async function decrypt(data: string, secret: string): Promise<string> {\n const [ivB64, cipherB64] = data.split(\".\");\n if (!ivB64 || !cipherB64) {\n throw new Error(\"decrypt: invalid ciphertext format\");\n }\n\n const key = await deriveKey(secret);\n const ivBytes = base64ToBuffer(ivB64);\n const iv = ivBytes.buffer.slice(\n ivBytes.byteOffset,\n ivBytes.byteOffset + ivBytes.byteLength\n ) as ArrayBuffer;\n\n const cipherBytes = base64ToBuffer(cipherB64);\n const cipherBuffer = cipherBytes.buffer.slice(\n cipherBytes.byteOffset,\n cipherBytes.byteOffset + cipherBytes.byteLength\n ) as ArrayBuffer;\n\n const plainBuffer = await crypto.subtle.decrypt({ name: ALGO, iv }, key, cipherBuffer);\n\n return getTextDecoder().decode(plainBuffer);\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction bufferToBase64(buffer: Uint8Array): string {\n return btoa(String.fromCharCode(...buffer))\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\nfunction base64ToBuffer(b64: string): Uint8Array {\n const padded = b64.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const binary = atob(padded);\n return Uint8Array.from(binary, (c) => c.charCodeAt(0));\n}\n","import type { AuthConfig, AuthTokens } from \"../types\";\nimport { encrypt, decrypt } from \"../utils/crypto\";\n\n/**\n * Manages storage, retrieval, and expiry checks for auth tokens.\n * Supports \"cookie\" and \"memory\" storage strategies.\n */\nexport class TokenManager {\n private memoryStore: AuthTokens | null = null;\n private readonly config: AuthConfig;\n\n constructor(config: AuthConfig) {\n this.config = config;\n }\n\n // ─── Public API ─────────────────────────────────────────────────────────────\n\n getTokens(): AuthTokens | null {\n if (this.config.token.storage === \"memory\") {\n return this.memoryStore;\n }\n return this.readFromCookie();\n }\n\n async setTokens(tokens: AuthTokens): Promise<void> {\n if (this.config.token.storage === \"memory\") {\n this.memoryStore = tokens;\n return;\n }\n await this.writeToCookie(tokens);\n }\n\n clearTokens(): void {\n this.memoryStore = null;\n if (this.config.token.storage === \"cookie\") {\n this.deleteCookie();\n }\n }\n\n isAccessExpired(tokens: AuthTokens): boolean {\n const threshold = (this.config.refreshThreshold ?? 60) * 1000;\n return Date.now() >= tokens.accessTokenExpiresAt - threshold;\n }\n\n isRefreshExpired(tokens: AuthTokens): boolean {\n if (!tokens.refreshTokenExpiresAt) return false;\n return Date.now() >= tokens.refreshTokenExpiresAt;\n }\n\n // ─── Cookie helpers (client-side only) ──────────────────────────────────────\n\n private cookieName(): string {\n return this.config.token.cookieName ?? \"next-token-auth.session\";\n }\n\n private readFromCookie(): AuthTokens | null {\n if (typeof document === \"undefined\") return null;\n\n const raw = getCookieValue(this.cookieName());\n if (!raw) return null;\n\n try {\n // Tokens are stored as JSON; encryption is applied server-side via\n // getServerSession. Client reads the plaintext access token from cookie.\n return JSON.parse(decodeURIComponent(raw)) as AuthTokens;\n } catch {\n return null;\n }\n }\n\n private async writeToCookie(tokens: AuthTokens): Promise<void> {\n if (typeof document === \"undefined\") return;\n\n const value = encodeURIComponent(JSON.stringify(tokens));\n const secure = this.config.token.secure !== false ? \"; Secure\" : \"\";\n const sameSite = this.config.token.sameSite ?? \"lax\";\n const maxAge = tokens.refreshTokenExpiresAt\n ? Math.floor((tokens.refreshTokenExpiresAt - Date.now()) / 1000)\n : 604800; // 7 days default\n\n document.cookie = [\n `${this.cookieName()}=${value}`,\n `Max-Age=${maxAge}`,\n `Path=/`,\n `SameSite=${sameSite}`,\n secure,\n ]\n .filter(Boolean)\n .join(\"; \");\n }\n\n private deleteCookie(): void {\n if (typeof document === \"undefined\") return;\n document.cookie = `${this.cookieName()}=; Max-Age=0; Path=/`;\n }\n\n // ─── Server-side helpers ─────────────────────────────────────────────────────\n\n /**\n * Encrypts tokens for secure server-side cookie storage.\n */\n async encryptTokens(tokens: AuthTokens): Promise<string> {\n return encrypt(JSON.stringify(tokens), this.config.secret);\n }\n\n /**\n * Decrypts tokens from a server-side cookie value.\n */\n async decryptTokens(ciphertext: string): Promise<AuthTokens | null> {\n try {\n const json = await decrypt(ciphertext, this.config.secret);\n return JSON.parse(json) as AuthTokens;\n } catch {\n return null;\n }\n }\n}\n\n// ─── Utility ──────────────────────────────────────────────────────────────────\n\nfunction getCookieValue(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n const match = document.cookie.match(\n new RegExp(`(?:^|;\\\\s*)${escapeRegex(name)}=([^;]*)`)\n );\n return match ? match[1] : null;\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import type {\n AuthConfig,\n AuthSession,\n AuthTokens,\n LoginInput,\n LoginResponse,\n} from \"../types\";\nimport { resolveAccessTokenExpiry, resolveRefreshTokenExpiry } from \"../utils/expiry\";\nimport { HttpClient } from \"./HttpClient\";\nimport { SessionManager } from \"./SessionManager\";\nimport { TokenManager } from \"./TokenManager\";\n\n/**\n * Central orchestrator for authentication operations.\n * Coordinates TokenManager, SessionManager, and HttpClient.\n */\nexport class AuthClient<User = unknown> {\n readonly tokenManager: TokenManager;\n readonly sessionManager: SessionManager<User>;\n readonly httpClient: HttpClient;\n\n private readonly config: AuthConfig<User>;\n private sessionListeners: Array<(session: AuthSession<User>) => void> = [];\n\n constructor(config: AuthConfig<User>) {\n this.config = config;\n this.tokenManager = new TokenManager(config as AuthConfig<unknown>);\n this.httpClient = new HttpClient(config as AuthConfig<unknown>, this.tokenManager);\n this.sessionManager = new SessionManager(\n config,\n this.tokenManager,\n this.httpClient\n );\n\n // Wire up the refresh callback\n this.httpClient.setRefreshFn(() => this.refresh());\n }\n\n // ─── Auth Operations ────────────────────────────────────────────────────────\n\n /**\n * Authenticates the user and stores tokens.\n */\n async login(input: LoginInput): Promise<AuthSession<User>> {\n const res = await this.httpClient.doFetch(\n this.httpClient.url(this.config.endpoints.login),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(input),\n }\n );\n\n if (!res.ok) {\n const error = await res.text();\n throw new Error(`Login failed (${res.status}): ${error}`);\n }\n\n const data = (await res.json()) as LoginResponse<User>;\n const tokens = this.buildTokens(data);\n\n await this.tokenManager.setTokens(tokens);\n await this.sessionManager.loadSession();\n\n const session = this.sessionManager.getSession();\n this.config.onLogin?.(session);\n this.notifyListeners(session);\n\n return session;\n }\n\n /**\n * Logs out the user, clears tokens, and optionally calls the backend.\n */\n async logout(): Promise<void> {\n const logoutEndpoint = this.config.endpoints.logout;\n\n if (logoutEndpoint) {\n try {\n await this.httpClient.fetch(this.httpClient.url(logoutEndpoint), {\n method: \"POST\",\n });\n } catch {\n // Best-effort logout\n }\n }\n\n this.tokenManager.clearTokens();\n this.sessionManager.clearSession();\n this.config.onLogout?.();\n this.notifyListeners(this.sessionManager.getSession());\n }\n\n /**\n * Refreshes the access token using the stored refresh token.\n * Returns true on success, false on failure.\n */\n async refresh(): Promise<boolean> {\n const tokens = this.tokenManager.getTokens();\n\n if (!tokens) return false;\n if (this.tokenManager.isRefreshExpired(tokens)) {\n await this.logout();\n return false;\n }\n\n try {\n const res = await this.httpClient.doFetch(\n this.httpClient.url(this.config.endpoints.refresh),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refreshToken: tokens.refreshToken }),\n }\n );\n\n if (!res.ok) {\n await this.logout();\n return false;\n }\n\n const data = (await res.json()) as LoginResponse<User>;\n const newTokens = this.buildTokens(data);\n\n await this.tokenManager.setTokens(newTokens);\n await this.sessionManager.refreshSession(newTokens);\n this.notifyListeners(this.sessionManager.getSession());\n\n return true;\n } catch (err) {\n this.config.onRefreshError?.(err);\n return false;\n }\n }\n\n /**\n * Loads the session from stored tokens (call on app mount).\n */\n async initialize(): Promise<AuthSession<User>> {\n const session = await this.sessionManager.loadSession();\n\n // Proactively refresh if access token is near expiry\n if (\n session.isAuthenticated &&\n session.tokens &&\n this.tokenManager.isAccessExpired(session.tokens) &&\n !this.tokenManager.isRefreshExpired(session.tokens)\n ) {\n await this.refresh();\n }\n\n return this.sessionManager.getSession();\n }\n\n getSession(): AuthSession<User> {\n return this.sessionManager.getSession();\n }\n\n /**\n * Returns the authenticated fetch wrapper.\n */\n get fetch(): HttpClient[\"fetch\"] {\n return this.httpClient.fetch.bind(this.httpClient);\n }\n\n // ─── Subscription ────────────────────────────────────────────────────────────\n\n subscribe(listener: (session: AuthSession<User>) => void): () => void {\n this.sessionListeners.push(listener);\n return () => {\n this.sessionListeners = this.sessionListeners.filter((l) => l !== listener);\n };\n }\n\n // ─── Private ────────────────────────────────────────────────────────────────\n\n private buildTokens(data: LoginResponse<User>): AuthTokens {\n const strategy = this.config.expiry?.strategy ?? \"hybrid\";\n const configAccess = this.config.expiry?.accessTokenExpiresIn;\n const configRefresh = this.config.expiry?.refreshTokenExpiresIn;\n\n return {\n accessToken: data.accessToken,\n refreshToken: data.refreshToken,\n accessTokenExpiresAt: resolveAccessTokenExpiry(data, configAccess, strategy),\n refreshTokenExpiresAt: resolveRefreshTokenExpiry(data, configRefresh, strategy),\n };\n }\n\n private notifyListeners(session: AuthSession<User>): void {\n for (const listener of this.sessionListeners) {\n listener(session);\n }\n }\n}\n","\"use client\";\n\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { AuthClient } from \"../core/AuthClient\";\nimport type { AuthConfig, AuthSession, LoginInput } from \"../types\";\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\ninterface AuthContextValue<User = unknown> {\n session: AuthSession<User>;\n isLoading: boolean;\n login: (input: LoginInput) => Promise<void>;\n logout: () => Promise<void>;\n refresh: () => Promise<void>;\n /** The underlying AuthClient for advanced use cases */\n client: AuthClient<User>;\n}\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\n// ─── Provider ─────────────────────────────────────────────────────────────────\n\ninterface AuthProviderProps<User = unknown> {\n config: AuthConfig<User>;\n children: React.ReactNode;\n}\n\nexport function AuthProvider<User = unknown>({\n config,\n children,\n}: AuthProviderProps<User>) {\n const clientRef = useRef<AuthClient<User> | null>(null);\n\n if (!clientRef.current) {\n clientRef.current = new AuthClient<User>(config);\n }\n\n const client = clientRef.current;\n\n const [session, setSession] = useState<AuthSession<User>>({\n user: null,\n tokens: null,\n isAuthenticated: false,\n });\n const [isLoading, setIsLoading] = useState(true);\n\n // Initialize session on mount\n useEffect(() => {\n let cancelled = false;\n\n client.initialize().then((s) => {\n if (!cancelled) {\n setSession(s);\n setIsLoading(false);\n }\n });\n\n // Subscribe to session changes\n const unsubscribe = client.subscribe((s) => {\n if (!cancelled) setSession(s);\n });\n\n return () => {\n cancelled = true;\n unsubscribe();\n };\n }, [client]);\n\n // Auto-refresh timer\n useEffect(() => {\n if (!config.autoRefresh) return;\n\n const interval = setInterval(async () => {\n const tokens = client.tokenManager.getTokens();\n if (\n tokens &&\n client.tokenManager.isAccessExpired(tokens) &&\n !client.tokenManager.isRefreshExpired(tokens)\n ) {\n await client.refresh();\n }\n }, 30_000); // check every 30s\n\n return () => clearInterval(interval);\n }, [client, config.autoRefresh]);\n\n const login = useCallback(\n async (input: LoginInput) => {\n setIsLoading(true);\n try {\n const s = await client.login(input);\n setSession(s);\n } finally {\n setIsLoading(false);\n }\n },\n [client]\n );\n\n const logout = useCallback(async () => {\n await client.logout();\n setSession({ user: null, tokens: null, isAuthenticated: false });\n }, [client]);\n\n const refresh = useCallback(async () => {\n await client.refresh();\n setSession(client.getSession());\n }, [client]);\n\n const value: AuthContextValue<User> = {\n session,\n isLoading,\n login,\n logout,\n refresh,\n client,\n };\n\n return (\n <AuthContext.Provider value={value as AuthContextValue}>\n {children}\n </AuthContext.Provider>\n );\n}\n\n// ─── Internal hook ────────────────────────────────────────────────────────────\n\nexport function useAuthContext<User = unknown>(): AuthContextValue<User> {\n const ctx = useContext(AuthContext);\n if (!ctx) {\n throw new Error(\"useAuthContext must be used within <AuthProvider>\");\n }\n return ctx as AuthContextValue<User>;\n}\n","\"use client\";\n\nimport type { AuthSession, LoginInput } from \"../../types\";\nimport { useAuthContext } from \"../AuthProvider\";\n\nexport interface UseAuthReturn<User = unknown> {\n session: AuthSession<User>;\n login: (input: LoginInput) => Promise<void>;\n logout: () => Promise<void>;\n refresh: () => Promise<void>;\n isLoading: boolean;\n}\n\n/**\n * Primary hook for authentication operations.\n *\n * @example\n * const { session, login, logout, isLoading } = useAuth();\n */\nexport function useAuth<User = unknown>(): UseAuthReturn<User> {\n const { session, login, logout, refresh, isLoading } =\n useAuthContext<User>();\n\n return { session, login, logout, refresh, isLoading };\n}\n","\"use client\";\n\nimport type { AuthSession } from \"../../types\";\nimport { useAuthContext } from \"../AuthProvider\";\n\n/**\n * Returns the current auth session without exposing login/logout actions.\n *\n * @example\n * const { user, isAuthenticated } = useSession();\n */\nexport function useSession<User = unknown>(): AuthSession<User> {\n return useAuthContext<User>().session;\n}\n","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { useAuthContext } from \"../AuthProvider\";\n\nexport interface UseRequireAuthOptions {\n /** Path to redirect unauthenticated users to. @default \"/login\" */\n redirectTo?: string;\n /** Called when the user is not authenticated (use for custom redirect logic) */\n onUnauthenticated?: () => void;\n}\n\n/**\n * Redirects unauthenticated users to the login page.\n * Works with both Next.js App Router and Pages Router.\n *\n * @example\n * // App Router (client component)\n * useRequireAuth({ redirectTo: \"/login\" });\n *\n * @example\n * // Custom handler\n * useRequireAuth({ onUnauthenticated: () => router.push(\"/login\") });\n */\nexport function useRequireAuth(options: UseRequireAuthOptions = {}): void {\n const { redirectTo = \"/login\", onUnauthenticated } = options;\n const { session, isLoading } = useAuthContext();\n\n useEffect(() => {\n if (isLoading) return;\n if (session.isAuthenticated) return;\n\n if (onUnauthenticated) {\n onUnauthenticated();\n return;\n }\n\n // Works in both App Router and Pages Router environments\n if (typeof window !== \"undefined\") {\n window.location.href = redirectTo;\n }\n }, [session.isAuthenticated, isLoading, redirectTo, onUnauthenticated]);\n}\n"]}
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "next-token-auth",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Production-grade authentication library for Next.js (App Router & Pages Router)",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
7
7
  "types": "./dist/index.d.ts",
8
8
  "repository": {
9
- "type": "git",
10
- "url": "https://github.com/TonyMike/tonymike-next-auth-kit.git"
11
- },
9
+ "type": "git",
10
+ "url": "https://github.com/TonyMike/tonymike-next-token-auth.git"
11
+ },
12
12
  "exports": {
13
13
  ".": {
14
14
  "types": "./dist/index.d.ts",