next-token-auth 1.0.14 → 1.0.15
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 +165 -65
- package/dist/{index-CejL5heu.d.mts → index-Csz5lfEv.d.mts} +30 -2
- package/dist/{index-CejL5heu.d.ts → index-Csz5lfEv.d.ts} +30 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +58 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +59 -32
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +4 -4
- package/dist/react/index.d.ts +4 -4
- package/dist/react/index.js +53 -538
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +54 -539
- package/dist/react/index.mjs.map +1 -1
- package/dist/server/index.d.mts +45 -7
- package/dist/server/index.d.ts +45 -7
- package/dist/server/index.js +178 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +178 -1
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,8 @@ A production-grade authentication library for Next.js. Handles access tokens, re
|
|
|
4
4
|
|
|
5
5
|
Works with both the App Router and Pages Router. Fully typed with TypeScript.
|
|
6
6
|
|
|
7
|
+
> **Breaking change in v1.1.0:** The secret is now server-side only. You must split your config into `AuthConfig` (server) and `ClientAuthConfig` (client), and mount `createAuthHandlers` at `app/api/auth/[action]/route.ts`. See the Quick Start below.
|
|
8
|
+
|
|
7
9
|
---
|
|
8
10
|
|
|
9
11
|
## The Problem
|
|
@@ -75,10 +77,10 @@ react-dom >= 18
|
|
|
75
77
|
|
|
76
78
|
## Quick Start
|
|
77
79
|
|
|
78
|
-
### 1. Create your config
|
|
80
|
+
### 1. Create your server config
|
|
79
81
|
|
|
80
82
|
```ts
|
|
81
|
-
// lib/auth.ts
|
|
83
|
+
// lib/auth.ts (SERVER-SIDE ONLY — never import in client components)
|
|
82
84
|
import type { AuthConfig } from "next-token-auth";
|
|
83
85
|
|
|
84
86
|
interface User {
|
|
@@ -88,7 +90,7 @@ interface User {
|
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
export const authConfig: AuthConfig<User> = {
|
|
91
|
-
baseUrl: process.env.
|
|
93
|
+
baseUrl: process.env.API_URL!, // No NEXT_PUBLIC_ prefix needed
|
|
92
94
|
|
|
93
95
|
endpoints: {
|
|
94
96
|
login: "/auth/login",
|
|
@@ -100,7 +102,8 @@ export const authConfig: AuthConfig<User> = {
|
|
|
100
102
|
routes: {
|
|
101
103
|
public: ["/", "/about"],
|
|
102
104
|
guestOnly: ["/login", "/register"],
|
|
103
|
-
protected: ["/dashboard
|
|
105
|
+
protected: ["/dashboard*"],
|
|
106
|
+
loginPath: "/login",
|
|
104
107
|
redirectAuthenticatedTo: "/dashboard",
|
|
105
108
|
},
|
|
106
109
|
|
|
@@ -111,7 +114,7 @@ export const authConfig: AuthConfig<User> = {
|
|
|
111
114
|
sameSite: "lax",
|
|
112
115
|
},
|
|
113
116
|
|
|
114
|
-
secret: process.env.AUTH_SECRET!,
|
|
117
|
+
secret: process.env.AUTH_SECRET!, // SERVER-SIDE ONLY
|
|
115
118
|
|
|
116
119
|
autoRefresh: true,
|
|
117
120
|
|
|
@@ -123,25 +126,55 @@ export const authConfig: AuthConfig<User> = {
|
|
|
123
126
|
};
|
|
124
127
|
```
|
|
125
128
|
|
|
126
|
-
### 2.
|
|
129
|
+
### 2. Create your client config
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
// lib/auth.client.ts (safe to import anywhere, including client components)
|
|
133
|
+
import type { ClientAuthConfig } from "next-token-auth";
|
|
134
|
+
|
|
135
|
+
export const clientAuthConfig: ClientAuthConfig = {
|
|
136
|
+
token: {
|
|
137
|
+
cookieName: "myapp.session",
|
|
138
|
+
},
|
|
139
|
+
autoRefresh: true,
|
|
140
|
+
};
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### 3. Mount the Route Handlers
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
// app/api/auth/[action]/route.ts
|
|
147
|
+
import { createAuthHandlers } from "next-token-auth/server";
|
|
148
|
+
import { authConfig } from "@/lib/auth";
|
|
149
|
+
|
|
150
|
+
export const { GET, POST } = createAuthHandlers(authConfig);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
This creates four endpoints automatically:
|
|
154
|
+
- `POST /api/auth/login` — authenticates and sets HttpOnly cookie
|
|
155
|
+
- `POST /api/auth/logout` — clears the session cookie
|
|
156
|
+
- `POST /api/auth/refresh` — refreshes the access token
|
|
157
|
+
- `GET /api/auth/session` — returns current user and auth status
|
|
158
|
+
|
|
159
|
+
### 4. Wrap your app with `AuthProvider`
|
|
127
160
|
|
|
128
161
|
```tsx
|
|
129
162
|
// app/layout.tsx
|
|
130
163
|
import { AuthProvider } from "next-token-auth/react";
|
|
131
|
-
import {
|
|
164
|
+
import { clientAuthConfig } from "@/lib/auth.client";
|
|
132
165
|
|
|
133
166
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
134
167
|
return (
|
|
135
168
|
<html lang="en">
|
|
136
169
|
<body>
|
|
137
|
-
<AuthProvider config={
|
|
170
|
+
<AuthProvider config={clientAuthConfig}>{children}</AuthProvider>
|
|
138
171
|
</body>
|
|
139
172
|
</html>
|
|
140
173
|
);
|
|
141
174
|
}
|
|
142
175
|
```
|
|
143
176
|
|
|
144
|
-
###
|
|
177
|
+
### 5. Use the hooks
|
|
145
178
|
|
|
146
179
|
```tsx
|
|
147
180
|
"use client";
|
|
@@ -155,6 +188,7 @@ export default function LoginPage() {
|
|
|
155
188
|
e.preventDefault();
|
|
156
189
|
const form = new FormData(e.currentTarget);
|
|
157
190
|
await login({ email: form.get("email"), password: form.get("password") });
|
|
191
|
+
window.location.href = "/dashboard";
|
|
158
192
|
}
|
|
159
193
|
|
|
160
194
|
return (
|
|
@@ -175,53 +209,75 @@ export default function LoginPage() {
|
|
|
175
209
|
|
|
176
210
|
### `AuthProvider`
|
|
177
211
|
|
|
178
|
-
Wrap your application once at the root. It
|
|
212
|
+
Wrap your application once at the root. It calls `/api/auth/session` on mount to restore the session from the HttpOnly cookie, then subscribes to session changes.
|
|
179
213
|
|
|
180
214
|
```tsx
|
|
181
|
-
<AuthProvider config={
|
|
215
|
+
<AuthProvider config={clientAuthConfig}>
|
|
182
216
|
{children}
|
|
183
217
|
</AuthProvider>
|
|
184
218
|
```
|
|
185
219
|
|
|
186
|
-
When `autoRefresh: true` is set, the provider
|
|
220
|
+
When `autoRefresh: true` is set, the provider calls `/api/auth/refresh` periodically based on `refreshThreshold`.
|
|
221
|
+
|
|
222
|
+
#### Client config reference (`ClientAuthConfig`)
|
|
223
|
+
|
|
224
|
+
This is what you pass to `AuthProvider` — it does NOT contain `secret` or `baseUrl`.
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
interface ClientAuthConfig {
|
|
228
|
+
token?: {
|
|
229
|
+
cookieName?: string; // default: "next-token-auth.session"
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
routes?: {
|
|
233
|
+
loginPath?: string; // where to redirect unauthenticated users (default: "/login")
|
|
234
|
+
redirectAuthenticatedTo?: string; // where to redirect authenticated users on guestOnly routes (default: "/dashboard")
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
autoRefresh?: boolean; // automatically refresh tokens before expiry
|
|
238
|
+
|
|
239
|
+
refreshThreshold?: number; // seconds before expiry to trigger refresh (default: 60)
|
|
240
|
+
|
|
241
|
+
// Lifecycle callbacks
|
|
242
|
+
onLogin?: (session: AuthSession) => void;
|
|
243
|
+
onLogout?: () => void;
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
#### Server config reference (`AuthConfig`)
|
|
187
248
|
|
|
188
|
-
|
|
249
|
+
This is used in `createAuthHandlers`, `authMiddleware`, `getServerSession`, and `withAuth`. Never import this in a client component.
|
|
189
250
|
|
|
190
251
|
```ts
|
|
191
252
|
interface AuthConfig<User = unknown> {
|
|
192
|
-
//
|
|
193
|
-
baseUrl: string;
|
|
253
|
+
baseUrl: string; // Backend API base URL (no NEXT_PUBLIC_ needed)
|
|
194
254
|
|
|
195
255
|
endpoints: {
|
|
196
256
|
login: string; // required
|
|
197
257
|
refresh: string; // required
|
|
198
258
|
register?: string;
|
|
199
259
|
logout?: string;
|
|
200
|
-
me?: string; // fetched
|
|
260
|
+
me?: string; // fetched to populate session.user
|
|
201
261
|
};
|
|
202
262
|
|
|
203
263
|
routes?: {
|
|
204
|
-
public: string[]; // always accessible
|
|
264
|
+
public: string[]; // always accessible
|
|
205
265
|
protected: string[]; // require auth, supports wildcard: "/dashboard*"
|
|
206
|
-
guestOnly?: string[]; // only accessible when NOT authenticated
|
|
266
|
+
guestOnly?: string[]; // only accessible when NOT authenticated
|
|
207
267
|
loginPath?: string; // where to redirect unauthenticated users (default: "/login")
|
|
208
|
-
redirectAuthenticatedTo?: string; // where to
|
|
268
|
+
redirectAuthenticatedTo?: string; // where to redirect authenticated users on guestOnly routes (default: "/dashboard")
|
|
209
269
|
};
|
|
210
270
|
|
|
211
271
|
token: {
|
|
212
272
|
storage: "cookie" | "memory";
|
|
213
|
-
cookieName?: string;
|
|
273
|
+
cookieName?: string;
|
|
214
274
|
secure?: boolean; // default: true
|
|
215
275
|
sameSite?: "strict" | "lax" | "none"; // default: "lax"
|
|
216
276
|
};
|
|
217
277
|
|
|
218
|
-
//
|
|
219
|
-
secret: string;
|
|
278
|
+
secret: string; // AES-GCM encryption key — SERVER-SIDE ONLY
|
|
220
279
|
|
|
221
|
-
// Automatically refresh the access token before it expires
|
|
222
280
|
autoRefresh?: boolean;
|
|
223
|
-
|
|
224
|
-
// Seconds before expiry to trigger a proactive refresh (default: 60)
|
|
225
281
|
refreshThreshold?: number;
|
|
226
282
|
|
|
227
283
|
expiry?: {
|
|
@@ -230,7 +286,6 @@ interface AuthConfig<User = unknown> {
|
|
|
230
286
|
strategy?: "backend" | "config" | "hybrid"; // default: "hybrid"
|
|
231
287
|
};
|
|
232
288
|
|
|
233
|
-
// Provide a custom fetch implementation (e.g. for testing)
|
|
234
289
|
fetchFn?: typeof fetch;
|
|
235
290
|
|
|
236
291
|
// Lifecycle callbacks
|
|
@@ -252,10 +307,10 @@ const { session, login, logout, refresh, isLoading } = useAuth<User>();
|
|
|
252
307
|
|
|
253
308
|
| Property | Type | Description |
|
|
254
309
|
|-------------|-----------------------------------------|--------------------------------------------------|
|
|
255
|
-
| `session` | `AuthSession<User>` | Current auth session
|
|
256
|
-
| `login` | `(input: LoginInput) => Promise<void>` | POST to
|
|
257
|
-
| `logout` | `() => Promise<void>` |
|
|
258
|
-
| `refresh` | `() => Promise<void>` |
|
|
310
|
+
| `session` | `AuthSession<User>` | Current auth session (user + isAuthenticated) |
|
|
311
|
+
| `login` | `(input: LoginInput) => Promise<void>` | POST to `/api/auth/login`, sets HttpOnly cookie |
|
|
312
|
+
| `logout` | `() => Promise<void>` | POST to `/api/auth/logout`, clears cookie |
|
|
313
|
+
| `refresh` | `() => Promise<void>` | POST to `/api/auth/refresh`, updates cookie |
|
|
259
314
|
| `isLoading` | `boolean` | `true` while initializing or during login |
|
|
260
315
|
|
|
261
316
|
`LoginInput` is an open object (`{ [key: string]: unknown }`), so you can pass any fields your backend expects.
|
|
@@ -299,18 +354,17 @@ The hook waits for `isLoading` to be `false` before acting, so it won't flash a
|
|
|
299
354
|
|
|
300
355
|
### Making Authenticated API Requests
|
|
301
356
|
|
|
302
|
-
|
|
357
|
+
Since tokens are stored in HttpOnly cookies (inaccessible to JavaScript), you cannot manually add `Authorization` headers from the client. Instead, your backend API routes should read the session cookie and extract the access token server-side.
|
|
358
|
+
|
|
359
|
+
For client-side requests to your own API:
|
|
303
360
|
|
|
304
361
|
```ts
|
|
305
362
|
"use client";
|
|
306
363
|
|
|
307
|
-
import { useAuth } from "next-token-auth/react";
|
|
308
|
-
|
|
309
364
|
export default function Orders() {
|
|
310
|
-
const { client } = useAuth();
|
|
311
|
-
|
|
312
365
|
async function fetchOrders() {
|
|
313
|
-
|
|
366
|
+
// The session cookie is automatically sent with this request
|
|
367
|
+
const res = await fetch("/api/orders");
|
|
314
368
|
const data = await res.json();
|
|
315
369
|
console.log(data);
|
|
316
370
|
}
|
|
@@ -319,19 +373,35 @@ export default function Orders() {
|
|
|
319
373
|
}
|
|
320
374
|
```
|
|
321
375
|
|
|
322
|
-
|
|
376
|
+
Then in your API route, read the session:
|
|
323
377
|
|
|
324
378
|
```ts
|
|
325
|
-
|
|
379
|
+
// app/api/orders/route.ts
|
|
380
|
+
import { getServerSession } from "next-token-auth/server";
|
|
381
|
+
import { authConfig } from "@/lib/auth";
|
|
382
|
+
import { cookies } from "next/headers";
|
|
326
383
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
384
|
+
export async function GET(req: Request) {
|
|
385
|
+
const cookieStore = await cookies();
|
|
386
|
+
const session = await getServerSession(
|
|
387
|
+
{ cookies: { get: (name) => cookieStore.get(name) } },
|
|
388
|
+
authConfig
|
|
389
|
+
);
|
|
390
|
+
|
|
391
|
+
if (!session.isAuthenticated) {
|
|
392
|
+
return Response.json({ error: "Unauthorized" }, { status: 401 });
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Use session.tokens.accessToken to call your backend
|
|
396
|
+
const res = await fetch(`${authConfig.baseUrl}/orders`, {
|
|
397
|
+
headers: { Authorization: `Bearer ${session.tokens!.accessToken}` },
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
return Response.json(await res.json());
|
|
401
|
+
}
|
|
332
402
|
```
|
|
333
403
|
|
|
334
|
-
|
|
404
|
+
This keeps tokens secure — they never leave the server.
|
|
335
405
|
|
|
336
406
|
---
|
|
337
407
|
|
|
@@ -378,12 +448,16 @@ export const authConfig: AuthConfig = {
|
|
|
378
448
|
```
|
|
379
449
|
|
|
380
450
|
```ts
|
|
381
|
-
// middleware.ts (
|
|
451
|
+
// middleware.ts (Next.js 13–15) or proxy.ts (Next.js 16+)
|
|
382
452
|
import { authMiddleware } from "next-token-auth/server";
|
|
383
453
|
import { authConfig } from "@/lib/auth";
|
|
384
454
|
|
|
455
|
+
// Next.js 13–15
|
|
385
456
|
export const middleware = authMiddleware(authConfig);
|
|
386
457
|
|
|
458
|
+
// Next.js 16+
|
|
459
|
+
export const proxy = authMiddleware(authConfig);
|
|
460
|
+
|
|
387
461
|
export const config = {
|
|
388
462
|
matcher: ["/sign-in", "/sign-up", "/app*", "/account*"],
|
|
389
463
|
};
|
|
@@ -428,36 +502,38 @@ Two things to keep in mind:
|
|
|
428
502
|
|
|
429
503
|
### How tokens are stored
|
|
430
504
|
|
|
431
|
-
|
|
432
|
-
|--------------|-----------------------------------------------------------------------|
|
|
433
|
-
| `"cookie"` | Serialized as JSON in a browser cookie with `Secure` + `SameSite` |
|
|
434
|
-
| `"memory"` | Held in a JavaScript variable — cleared on page refresh |
|
|
505
|
+
Tokens are always stored in HttpOnly cookies (encrypted with AES-GCM). The `storage: "memory"` option is deprecated — HttpOnly cookies are more secure because JavaScript in the browser cannot access them.
|
|
435
506
|
|
|
436
|
-
|
|
507
|
+
The cookie is set by the `/api/auth/login` Route Handler (created via `createAuthHandlers`) and read by the middleware and `getServerSession`.
|
|
437
508
|
|
|
438
509
|
### Session restore on page load
|
|
439
510
|
|
|
440
|
-
When `AuthProvider` mounts, it calls `
|
|
511
|
+
When `AuthProvider` mounts, it calls `GET /api/auth/session`, which:
|
|
512
|
+
|
|
513
|
+
1. Reads the encrypted session cookie server-side
|
|
514
|
+
2. Decrypts it using your `secret`
|
|
515
|
+
3. Checks whether the refresh token is expired
|
|
516
|
+
4. If a `me` endpoint is configured, fetches the user profile
|
|
517
|
+
5. Returns `{ user, isAuthenticated }` to the client
|
|
441
518
|
|
|
442
|
-
|
|
443
|
-
2. Checks whether the access token is expired (accounting for `refreshThreshold`)
|
|
444
|
-
3. If the access token is near expiry but the refresh token is still valid, it silently refreshes
|
|
445
|
-
4. If a `me` endpoint is configured, it fetches the user profile to populate `session.user`
|
|
446
|
-
5. Updates React state — `isLoading` flips to `false` once complete
|
|
519
|
+
The client never sees the raw tokens — only the user object and auth status.
|
|
447
520
|
|
|
448
521
|
### Automatic refresh
|
|
449
522
|
|
|
450
|
-
When `autoRefresh: true`, the provider
|
|
523
|
+
When `autoRefresh: true`, the provider calls `POST /api/auth/refresh` periodically (based on `refreshThreshold`, default 60 seconds before expiry). The Route Handler:
|
|
451
524
|
|
|
452
|
-
|
|
525
|
+
1. Reads the encrypted cookie
|
|
526
|
+
2. Checks if the refresh token is still valid
|
|
527
|
+
3. Calls your backend's refresh endpoint with the refresh token
|
|
528
|
+
4. Encrypts the new tokens and updates the HttpOnly cookie
|
|
453
529
|
|
|
454
530
|
### Refresh flow
|
|
455
531
|
|
|
456
532
|
```
|
|
457
|
-
|
|
533
|
+
Client detects expiry → POST /api/auth/refresh → backend refresh endpoint → new encrypted cookie set
|
|
458
534
|
```
|
|
459
535
|
|
|
460
|
-
If the refresh token is expired, the
|
|
536
|
+
If the refresh token is expired, the session is cleared.
|
|
461
537
|
|
|
462
538
|
---
|
|
463
539
|
|
|
@@ -567,7 +643,7 @@ The `parseExpiry` utility accepts:
|
|
|
567
643
|
```ts
|
|
568
644
|
interface AuthSession<User = unknown> {
|
|
569
645
|
user: User | null;
|
|
570
|
-
tokens: AuthTokens | null;
|
|
646
|
+
tokens: AuthTokens | null; // always null on client-side (HttpOnly)
|
|
571
647
|
isAuthenticated: boolean;
|
|
572
648
|
}
|
|
573
649
|
|
|
@@ -587,6 +663,28 @@ interface LoginResponse<User = unknown> {
|
|
|
587
663
|
refreshTokenExpiresIn?: number | string;
|
|
588
664
|
}
|
|
589
665
|
|
|
666
|
+
// Server-side config (used in createAuthHandlers, middleware, getServerSession)
|
|
667
|
+
interface AuthConfig<User = unknown> {
|
|
668
|
+
baseUrl: string;
|
|
669
|
+
secret: string; // SERVER-SIDE ONLY
|
|
670
|
+
endpoints: { login: string; refresh: string; logout?: string; me?: string };
|
|
671
|
+
token: { storage: "cookie" | "memory"; cookieName?: string; secure?: boolean; sameSite?: string };
|
|
672
|
+
routes?: { public: string[]; protected: string[]; guestOnly?: string[]; loginPath?: string; redirectAuthenticatedTo?: string };
|
|
673
|
+
expiry?: { accessTokenExpiresIn?: number | string; refreshTokenExpiresIn?: number | string; strategy?: "backend" | "config" | "hybrid" };
|
|
674
|
+
autoRefresh?: boolean;
|
|
675
|
+
refreshThreshold?: number;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// Client-side config (used in AuthProvider)
|
|
679
|
+
interface ClientAuthConfig {
|
|
680
|
+
token?: { cookieName?: string };
|
|
681
|
+
routes?: { loginPath?: string; redirectAuthenticatedTo?: string };
|
|
682
|
+
autoRefresh?: boolean;
|
|
683
|
+
refreshThreshold?: number;
|
|
684
|
+
onLogin?: (session: AuthSession) => void;
|
|
685
|
+
onLogout?: () => void;
|
|
686
|
+
}
|
|
687
|
+
|
|
590
688
|
type ExpiryInput = number | string;
|
|
591
689
|
type ExpiryStrategy = "backend" | "config" | "hybrid";
|
|
592
690
|
```
|
|
@@ -606,11 +704,13 @@ All types are exported from the root `next-token-auth` import.
|
|
|
606
704
|
|
|
607
705
|
## Security Notes
|
|
608
706
|
|
|
609
|
-
-
|
|
610
|
-
-
|
|
707
|
+
- All tokens are stored in HttpOnly cookies — JavaScript in the browser cannot read them
|
|
708
|
+
- Session cookies are AES-GCM encrypted server-side using your `secret`
|
|
709
|
+
- The `secret` never leaves the server — it's only used in Route Handlers, middleware, and `getServerSession`
|
|
710
|
+
- `AuthProvider` receives `ClientAuthConfig` which does not contain `secret` or `baseUrl`
|
|
611
711
|
- Use a random 32-character string for `secret` in production — never commit it
|
|
612
|
-
-
|
|
613
|
-
-
|
|
712
|
+
- Cookies use `Secure` and `SameSite` flags by default for CSRF protection
|
|
713
|
+
- The `"memory"` storage mode is no longer recommended — HttpOnly cookies are more secure
|
|
614
714
|
|
|
615
715
|
---
|
|
616
716
|
|
|
@@ -25,6 +25,10 @@ interface LoginResponse<User = unknown> {
|
|
|
25
25
|
accessTokenExpiresIn?: number | string;
|
|
26
26
|
refreshTokenExpiresIn?: number | string;
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Full auth configuration — SERVER-SIDE ONLY.
|
|
30
|
+
* Never pass this to AuthProvider or any client component.
|
|
31
|
+
*/
|
|
28
32
|
interface AuthConfig<User = unknown> {
|
|
29
33
|
/** Base URL of your backend API */
|
|
30
34
|
baseUrl: string;
|
|
@@ -63,7 +67,7 @@ interface AuthConfig<User = unknown> {
|
|
|
63
67
|
secure?: boolean;
|
|
64
68
|
sameSite?: "strict" | "lax" | "none";
|
|
65
69
|
};
|
|
66
|
-
/** Secret used for encrypting stored tokens */
|
|
70
|
+
/** Secret used for encrypting stored tokens — SERVER-SIDE ONLY */
|
|
67
71
|
secret: string;
|
|
68
72
|
/** Automatically refresh access token before expiry */
|
|
69
73
|
autoRefresh?: boolean;
|
|
@@ -92,5 +96,29 @@ interface AuthConfig<User = unknown> {
|
|
|
92
96
|
/** Called when token refresh fails */
|
|
93
97
|
onRefreshError?: (error: unknown) => void;
|
|
94
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Client-safe auth configuration — safe to pass to AuthProvider.
|
|
101
|
+
* Does not contain secret or baseUrl.
|
|
102
|
+
*/
|
|
103
|
+
interface ClientAuthConfig {
|
|
104
|
+
token?: {
|
|
105
|
+
cookieName?: string;
|
|
106
|
+
};
|
|
107
|
+
routes?: {
|
|
108
|
+
loginPath?: string;
|
|
109
|
+
redirectAuthenticatedTo?: string;
|
|
110
|
+
};
|
|
111
|
+
/** Automatically refresh access token before expiry */
|
|
112
|
+
autoRefresh?: boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Seconds before expiry to trigger a proactive refresh.
|
|
115
|
+
* @default 60
|
|
116
|
+
*/
|
|
117
|
+
refreshThreshold?: number;
|
|
118
|
+
/** Called after a successful login */
|
|
119
|
+
onLogin?: (session: AuthSession) => void;
|
|
120
|
+
/** Called after logout */
|
|
121
|
+
onLogout?: () => void;
|
|
122
|
+
}
|
|
95
123
|
|
|
96
|
-
export type { AuthConfig as A, ExpiryInput as E, LoginInput as L, AuthSession as a, AuthTokens as b, ExpiryStrategy as c, LoginResponse as d };
|
|
124
|
+
export type { AuthConfig as A, ClientAuthConfig as C, ExpiryInput as E, LoginInput as L, AuthSession as a, AuthTokens as b, ExpiryStrategy as c, LoginResponse as d };
|
|
@@ -25,6 +25,10 @@ interface LoginResponse<User = unknown> {
|
|
|
25
25
|
accessTokenExpiresIn?: number | string;
|
|
26
26
|
refreshTokenExpiresIn?: number | string;
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Full auth configuration — SERVER-SIDE ONLY.
|
|
30
|
+
* Never pass this to AuthProvider or any client component.
|
|
31
|
+
*/
|
|
28
32
|
interface AuthConfig<User = unknown> {
|
|
29
33
|
/** Base URL of your backend API */
|
|
30
34
|
baseUrl: string;
|
|
@@ -63,7 +67,7 @@ interface AuthConfig<User = unknown> {
|
|
|
63
67
|
secure?: boolean;
|
|
64
68
|
sameSite?: "strict" | "lax" | "none";
|
|
65
69
|
};
|
|
66
|
-
/** Secret used for encrypting stored tokens */
|
|
70
|
+
/** Secret used for encrypting stored tokens — SERVER-SIDE ONLY */
|
|
67
71
|
secret: string;
|
|
68
72
|
/** Automatically refresh access token before expiry */
|
|
69
73
|
autoRefresh?: boolean;
|
|
@@ -92,5 +96,29 @@ interface AuthConfig<User = unknown> {
|
|
|
92
96
|
/** Called when token refresh fails */
|
|
93
97
|
onRefreshError?: (error: unknown) => void;
|
|
94
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Client-safe auth configuration — safe to pass to AuthProvider.
|
|
101
|
+
* Does not contain secret or baseUrl.
|
|
102
|
+
*/
|
|
103
|
+
interface ClientAuthConfig {
|
|
104
|
+
token?: {
|
|
105
|
+
cookieName?: string;
|
|
106
|
+
};
|
|
107
|
+
routes?: {
|
|
108
|
+
loginPath?: string;
|
|
109
|
+
redirectAuthenticatedTo?: string;
|
|
110
|
+
};
|
|
111
|
+
/** Automatically refresh access token before expiry */
|
|
112
|
+
autoRefresh?: boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Seconds before expiry to trigger a proactive refresh.
|
|
115
|
+
* @default 60
|
|
116
|
+
*/
|
|
117
|
+
refreshThreshold?: number;
|
|
118
|
+
/** Called after a successful login */
|
|
119
|
+
onLogin?: (session: AuthSession) => void;
|
|
120
|
+
/** Called after logout */
|
|
121
|
+
onLogout?: () => void;
|
|
122
|
+
}
|
|
95
123
|
|
|
96
|
-
export type { AuthConfig as A, ExpiryInput as E, LoginInput as L, AuthSession as a, AuthTokens as b, ExpiryStrategy as c, LoginResponse as d };
|
|
124
|
+
export type { AuthConfig as A, ClientAuthConfig as C, ExpiryInput as E, LoginInput as L, AuthSession as a, AuthTokens as b, ExpiryStrategy as c, LoginResponse as d };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AuthConfig, b as AuthTokens, a as AuthSession, L as LoginInput, E as ExpiryInput } from './index-
|
|
2
|
-
export { c as ExpiryStrategy, d as LoginResponse } from './index-
|
|
1
|
+
import { A as AuthConfig, b as AuthTokens, a as AuthSession, L as LoginInput, E as ExpiryInput } from './index-Csz5lfEv.mjs';
|
|
2
|
+
export { C as ClientAuthConfig, c as ExpiryStrategy, d as LoginResponse } from './index-Csz5lfEv.mjs';
|
|
3
3
|
export { AuthProvider, UseAuthReturn, UseRequireAuthOptions, useAuth, useRequireAuth, useSession } from './react/index.mjs';
|
|
4
4
|
import 'react/jsx-runtime';
|
|
5
5
|
import 'react';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AuthConfig, b as AuthTokens, a as AuthSession, L as LoginInput, E as ExpiryInput } from './index-
|
|
2
|
-
export { c as ExpiryStrategy, d as LoginResponse } from './index-
|
|
1
|
+
import { A as AuthConfig, b as AuthTokens, a as AuthSession, L as LoginInput, E as ExpiryInput } from './index-Csz5lfEv.js';
|
|
2
|
+
export { C as ClientAuthConfig, c as ExpiryStrategy, d as LoginResponse } from './index-Csz5lfEv.js';
|
|
3
3
|
export { AuthProvider, UseAuthReturn, UseRequireAuthOptions, useAuth, useRequireAuth, useSession } from './react/index.js';
|
|
4
4
|
import 'react/jsx-runtime';
|
|
5
5
|
import 'react';
|