@inai-dev/nextjs 0.1.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +369 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +63 -16
- package/dist/middleware.cjs.map +1 -1
- package/dist/middleware.d.cts +1 -0
- package/dist/middleware.d.ts +1 -0
- package/dist/middleware.js +64 -16
- package/dist/middleware.js.map +1 -1
- package/dist/server.cjs +27 -18
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +16 -5
- package/dist/server.d.ts +16 -5
- package/dist/server.js +9 -4
- package/dist/server.js.map +1 -1
- package/package.json +17 -7
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @inai-dev/nextjs
|
|
2
2
|
|
|
3
|
-
Full Next.js integration for InAI Auth. Includes middleware, server-side helpers, API route handlers,
|
|
3
|
+
Full Next.js integration for InAI Auth. Includes middleware, server-side auth helpers, API route handlers, React hooks, and UI components.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -8,72 +8,410 @@ Full Next.js integration for InAI Auth. Includes middleware, server-side helpers
|
|
|
8
8
|
npm install @inai-dev/nextjs
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
### 1. Environment Variables
|
|
11
|
+
## Environment Variables
|
|
14
12
|
|
|
15
13
|
```env
|
|
14
|
+
# Required — your publishable key (client-side accessible)
|
|
16
15
|
NEXT_PUBLIC_INAI_PUBLISHABLE_KEY=pk_live_...
|
|
17
|
-
|
|
16
|
+
|
|
17
|
+
# Optional — API URL overrides (defaults to https://apiauth.inai.dev)
|
|
18
|
+
INAI_API_URL=https://apiauth.inai.dev
|
|
19
|
+
NEXT_PUBLIC_INAI_API_URL=https://apiauth.inai.dev
|
|
18
20
|
```
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
The API URL is resolved in this order:
|
|
23
|
+
1. Explicit config via `configureAuth({ apiUrl: "..." })`
|
|
24
|
+
2. `INAI_API_URL` or `NEXT_PUBLIC_INAI_API_URL` environment variable
|
|
25
|
+
3. Default: `https://apiauth.inai.dev`
|
|
26
|
+
|
|
27
|
+
## Setup
|
|
28
|
+
|
|
29
|
+
### 1. Middleware
|
|
21
30
|
|
|
22
31
|
```ts
|
|
23
32
|
// middleware.ts
|
|
24
|
-
import {
|
|
33
|
+
import { inaiAuthMiddleware } from "@inai-dev/nextjs/middleware";
|
|
25
34
|
|
|
26
|
-
export default
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
export default inaiAuthMiddleware({
|
|
36
|
+
publicRoutes: ["/", "/about", "/login"],
|
|
37
|
+
signInUrl: "/login",
|
|
29
38
|
});
|
|
30
39
|
|
|
31
40
|
export const config = { matcher: ["/((?!_next|static|favicon.ico).*)"] };
|
|
32
41
|
```
|
|
33
42
|
|
|
34
|
-
###
|
|
43
|
+
### 2. Provider
|
|
35
44
|
|
|
36
45
|
```tsx
|
|
37
46
|
// app/layout.tsx
|
|
38
|
-
import {
|
|
47
|
+
import { InAIAuthProvider } from "@inai-dev/nextjs";
|
|
39
48
|
|
|
40
|
-
export default function RootLayout({ children }) {
|
|
41
|
-
return
|
|
49
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
50
|
+
return (
|
|
51
|
+
<html>
|
|
52
|
+
<body>
|
|
53
|
+
<InAIAuthProvider>{children}</InAIAuthProvider>
|
|
54
|
+
</body>
|
|
55
|
+
</html>
|
|
56
|
+
);
|
|
42
57
|
}
|
|
43
58
|
```
|
|
44
59
|
|
|
45
|
-
###
|
|
60
|
+
### 3. API Routes
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
// app/api/auth/[...inai]/route.ts
|
|
64
|
+
import { createAuthRoutes } from "@inai-dev/nextjs/server";
|
|
65
|
+
|
|
66
|
+
export const { GET, POST } = createAuthRoutes();
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Handles the following endpoints automatically:
|
|
70
|
+
- `POST /api/auth/login` — User login
|
|
71
|
+
- `POST /api/auth/register` — User registration
|
|
72
|
+
- `POST /api/auth/mfa-challenge` — MFA verification
|
|
73
|
+
- `POST /api/auth/refresh` — Token refresh
|
|
74
|
+
- `POST /api/auth/logout` — User logout
|
|
75
|
+
|
|
76
|
+
#### Platform API Routes
|
|
77
|
+
|
|
78
|
+
For multi-tenant platform authentication:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
// app/api/auth/[...inai]/route.ts
|
|
82
|
+
import { createPlatformAuthRoutes } from "@inai-dev/nextjs/server";
|
|
83
|
+
|
|
84
|
+
export const { GET, POST } = createPlatformAuthRoutes();
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Server-Side Auth
|
|
88
|
+
|
|
89
|
+
### `auth()`
|
|
90
|
+
|
|
91
|
+
Returns a `ServerAuthObject` with the current authentication state.
|
|
46
92
|
|
|
47
93
|
```ts
|
|
48
|
-
// app/dashboard/page.tsx
|
|
49
94
|
import { auth } from "@inai-dev/nextjs/server";
|
|
50
95
|
|
|
51
96
|
export default async function Dashboard() {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
97
|
+
const { userId, has, protect, redirectToSignIn, getToken } = await auth();
|
|
98
|
+
|
|
99
|
+
// Check if user is authenticated
|
|
100
|
+
if (!userId) {
|
|
101
|
+
redirectToSignIn({ returnTo: "/dashboard" });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Check roles/permissions
|
|
105
|
+
if (has({ role: "admin" })) {
|
|
106
|
+
// admin-only logic
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Protect — throws redirect if unauthorized
|
|
110
|
+
const authed = protect({ permission: "posts:write" });
|
|
111
|
+
|
|
112
|
+
// Get the access token
|
|
113
|
+
const token = await getToken();
|
|
114
|
+
|
|
115
|
+
return <p>User: {userId}</p>;
|
|
55
116
|
}
|
|
56
117
|
```
|
|
57
118
|
|
|
58
|
-
|
|
119
|
+
**`ServerAuthObject`:**
|
|
120
|
+
|
|
121
|
+
| Property | Type | Description |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| `userId` | `string \| null` | Current user ID |
|
|
124
|
+
| `tenantId` | `string \| null` | Tenant ID |
|
|
125
|
+
| `appId` | `string \| null` | Application ID |
|
|
126
|
+
| `envId` | `string \| null` | Environment ID |
|
|
127
|
+
| `orgId` | `string \| null` | Active organization ID |
|
|
128
|
+
| `orgRole` | `string \| null` | Role in active organization |
|
|
129
|
+
| `sessionId` | `string \| null` | Session ID |
|
|
130
|
+
| `getToken()` | `() => Promise<string \| null>` | Get the access token |
|
|
131
|
+
| `has(params)` | `({ role?, permission? }) => boolean` | Check role or permission |
|
|
132
|
+
| `protect(params?)` | `({ role?, permission?, redirectTo? }) => ProtectedAuthObject` | Assert auth or redirect |
|
|
133
|
+
| `redirectToSignIn(opts?)` | `({ returnTo? }) => never` | Redirect to sign-in page |
|
|
134
|
+
|
|
135
|
+
### `currentUser()`
|
|
136
|
+
|
|
137
|
+
Returns the full user object, or `null` if not authenticated.
|
|
59
138
|
|
|
60
139
|
```ts
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
export
|
|
140
|
+
import { currentUser } from "@inai-dev/nextjs/server";
|
|
141
|
+
|
|
142
|
+
export default async function Profile() {
|
|
143
|
+
const user = await currentUser();
|
|
144
|
+
if (!user) return null;
|
|
145
|
+
|
|
146
|
+
return <p>{user.email}</p>;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Force a fresh fetch from the API (bypasses cached session)
|
|
150
|
+
const freshUser = await currentUser({ fresh: true });
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## React Hooks
|
|
154
|
+
|
|
155
|
+
All hooks are imported from `@inai-dev/nextjs`.
|
|
156
|
+
|
|
157
|
+
### `useAuth()`
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
const { isLoaded, isSignedIn, userId, has, signOut } = useAuth();
|
|
161
|
+
|
|
162
|
+
has({ role: "admin" }); // check role
|
|
163
|
+
has({ permission: "read" }); // check permission
|
|
164
|
+
await signOut();
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### `useUser()`
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
const { isLoaded, isSignedIn, user } = useUser();
|
|
171
|
+
// user: UserResource | null
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### `useSession()`
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
const { isLoaded, isSignedIn, userId, tenantId, orgId, orgRole } = useSession();
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### `useOrganization()`
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
const { isLoaded, orgId, orgRole } = useOrganization();
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### `useSignIn()`
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
const { signIn, isLoading, error, status, reset } = useSignIn();
|
|
190
|
+
|
|
191
|
+
await signIn.create({ identifier: "user@example.com", password: "..." });
|
|
192
|
+
// status: "idle" | "loading" | "needs_mfa" | "complete" | "error"
|
|
193
|
+
|
|
194
|
+
// MFA flow
|
|
195
|
+
await signIn.attemptMFA({ code: "123456" });
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### `useSignUp()`
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
const { signUp, isLoading, error, status, reset } = useSignUp();
|
|
202
|
+
|
|
203
|
+
await signUp.create({
|
|
204
|
+
email: "user@example.com",
|
|
205
|
+
password: "...",
|
|
206
|
+
firstName: "Jane",
|
|
207
|
+
lastName: "Doe",
|
|
208
|
+
});
|
|
209
|
+
// status: "idle" | "loading" | "needs_email_verification" | "complete" | "error"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## React Components
|
|
213
|
+
|
|
214
|
+
All components are imported from `@inai-dev/nextjs`.
|
|
215
|
+
|
|
216
|
+
### `<Protect>`
|
|
217
|
+
|
|
218
|
+
Renders children only if the user has the required role or permission.
|
|
219
|
+
|
|
220
|
+
```tsx
|
|
221
|
+
<Protect role="admin" fallback={<p>Access denied</p>}>
|
|
222
|
+
<AdminPanel />
|
|
223
|
+
</Protect>
|
|
224
|
+
|
|
225
|
+
<Protect permission="posts:write">
|
|
226
|
+
<Editor />
|
|
227
|
+
</Protect>
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### `<SignedIn>` / `<SignedOut>`
|
|
231
|
+
|
|
232
|
+
Conditional rendering based on authentication state.
|
|
233
|
+
|
|
234
|
+
```tsx
|
|
235
|
+
<SignedIn>
|
|
236
|
+
<p>Welcome back!</p>
|
|
237
|
+
</SignedIn>
|
|
238
|
+
<SignedOut>
|
|
239
|
+
<p>Please sign in.</p>
|
|
240
|
+
</SignedOut>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### `<PermissionGate>`
|
|
244
|
+
|
|
245
|
+
Permission-based access control.
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
<PermissionGate permission="billing:manage" fallback={<p>No access</p>}>
|
|
249
|
+
<BillingSettings />
|
|
250
|
+
</PermissionGate>
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### `<UserButton>`
|
|
254
|
+
|
|
255
|
+
User profile menu with avatar and dropdown.
|
|
256
|
+
|
|
257
|
+
```tsx
|
|
258
|
+
<UserButton
|
|
259
|
+
afterSignOutUrl="/"
|
|
260
|
+
showName
|
|
261
|
+
menuItems={[{ label: "Settings", onClick: () => router.push("/settings") }]}
|
|
262
|
+
appearance={{ buttonSize: 36, buttonBg: "#1a1a2e" }}
|
|
263
|
+
/>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### `<SignIn>`
|
|
267
|
+
|
|
268
|
+
Sign-in form with MFA support.
|
|
269
|
+
|
|
270
|
+
```tsx
|
|
271
|
+
<SignIn
|
|
272
|
+
redirectUrl="/dashboard"
|
|
273
|
+
onSuccess={() => console.log("Signed in!")}
|
|
274
|
+
onMFARequired={(mfaToken) => router.push("/mfa")}
|
|
275
|
+
/>
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### `<OrganizationSwitcher>`
|
|
279
|
+
|
|
280
|
+
Organization switching dropdown.
|
|
281
|
+
|
|
282
|
+
```tsx
|
|
283
|
+
<OrganizationSwitcher />
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Advanced Configuration
|
|
287
|
+
|
|
288
|
+
### `configureAuth()` / `getAuthConfig()`
|
|
289
|
+
|
|
290
|
+
Set global configuration early in your app (e.g., in `layout.tsx` or a server initialization file).
|
|
291
|
+
|
|
292
|
+
```ts
|
|
293
|
+
import { configureAuth, getAuthConfig } from "@inai-dev/nextjs/server";
|
|
294
|
+
|
|
295
|
+
configureAuth({
|
|
296
|
+
signInUrl: "/login",
|
|
297
|
+
signUpUrl: "/register",
|
|
298
|
+
afterSignInUrl: "/dashboard",
|
|
299
|
+
afterSignOutUrl: "/",
|
|
300
|
+
apiUrl: "https://apiauth.inai.dev",
|
|
301
|
+
publishableKey: "pk_live_...",
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
const config = getAuthConfig();
|
|
305
|
+
// { signInUrl, signUpUrl, afterSignInUrl, afterSignOutUrl, apiUrl, publishableKey }
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### `createRouteMatcher()`
|
|
309
|
+
|
|
310
|
+
Create a reusable route matcher for middleware logic.
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
import { createRouteMatcher } from "@inai-dev/nextjs/middleware";
|
|
314
|
+
|
|
315
|
+
const isPublic = createRouteMatcher(["/", "/about", "/api/(.*)"]);
|
|
316
|
+
const isAdmin = createRouteMatcher(["/admin(.*)"]);
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### `withInAIAuth()`
|
|
320
|
+
|
|
321
|
+
Compose InAI auth with your existing middleware.
|
|
322
|
+
|
|
323
|
+
```ts
|
|
324
|
+
import { withInAIAuth } from "@inai-dev/nextjs/middleware";
|
|
325
|
+
|
|
326
|
+
export default withInAIAuth(
|
|
327
|
+
(req) => {
|
|
328
|
+
// Your custom middleware logic
|
|
329
|
+
return NextResponse.next();
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
publicRoutes: ["/", "/login"],
|
|
333
|
+
signInUrl: "/login",
|
|
334
|
+
beforeAuth: (req) => {
|
|
335
|
+
// Runs before auth check
|
|
336
|
+
},
|
|
337
|
+
afterAuth: (auth, req) => {
|
|
338
|
+
// Runs after auth check
|
|
339
|
+
if (auth.userId && req.nextUrl.pathname === "/login") {
|
|
340
|
+
return NextResponse.redirect(new URL("/dashboard", req.url));
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
}
|
|
344
|
+
);
|
|
64
345
|
```
|
|
65
346
|
|
|
66
|
-
## Exports
|
|
347
|
+
## Exports Reference
|
|
67
348
|
|
|
68
|
-
|
|
69
|
-
- `@inai-dev/nextjs/server` — `auth()`, `currentUser()`, server-side helpers
|
|
70
|
-
- `@inai-dev/nextjs/middleware` — `authMiddleware()`
|
|
349
|
+
### `@inai-dev/nextjs`
|
|
71
350
|
|
|
72
|
-
|
|
351
|
+
| Export | Kind | Description |
|
|
352
|
+
|---|---|---|
|
|
353
|
+
| `InAIAuthProvider` | Component | Auth context provider |
|
|
354
|
+
| `Protect` | Component | Role/permission gate |
|
|
355
|
+
| `SignedIn` | Component | Renders when signed in |
|
|
356
|
+
| `SignedOut` | Component | Renders when signed out |
|
|
357
|
+
| `PermissionGate` | Component | Permission-based gate |
|
|
358
|
+
| `UserButton` | Component | User profile menu |
|
|
359
|
+
| `SignIn` | Component | Sign-in form |
|
|
360
|
+
| `OrganizationSwitcher` | Component | Org switcher |
|
|
361
|
+
| `useAuth` | Hook | Auth state & actions |
|
|
362
|
+
| `useUser` | Hook | User data |
|
|
363
|
+
| `useSession` | Hook | Session info |
|
|
364
|
+
| `useOrganization` | Hook | Organization data |
|
|
365
|
+
| `useSignIn` | Hook | Sign-in flow |
|
|
366
|
+
| `useSignUp` | Hook | Sign-up flow |
|
|
367
|
+
| `COOKIE_AUTH_TOKEN` | Constant | `"auth_token"` |
|
|
368
|
+
| `COOKIE_REFRESH_TOKEN` | Constant | `"refresh_token"` |
|
|
369
|
+
| `COOKIE_AUTH_SESSION` | Constant | `"auth_session"` |
|
|
73
370
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
371
|
+
### `@inai-dev/nextjs/server`
|
|
372
|
+
|
|
373
|
+
| Export | Kind | Description |
|
|
374
|
+
|---|---|---|
|
|
375
|
+
| `auth` | Function | Get `ServerAuthObject` |
|
|
376
|
+
| `currentUser` | Function | Get current user |
|
|
377
|
+
| `createAuthRoutes` | Function | App user auth routes |
|
|
378
|
+
| `createPlatformAuthRoutes` | Function | Platform auth routes |
|
|
379
|
+
| `configureAuth` | Function | Set global config |
|
|
380
|
+
| `getAuthConfig` | Function | Get resolved config |
|
|
381
|
+
| `setAuthCookies` | Function | Set auth cookies |
|
|
382
|
+
| `clearAuthCookies` | Function | Clear auth cookies |
|
|
383
|
+
| `getAuthTokenFromCookies` | Function | Get access token |
|
|
384
|
+
| `getRefreshTokenFromCookies` | Function | Get refresh token |
|
|
385
|
+
|
|
386
|
+
### `@inai-dev/nextjs/middleware`
|
|
387
|
+
|
|
388
|
+
| Export | Kind | Description |
|
|
389
|
+
|---|---|---|
|
|
390
|
+
| `inaiAuthMiddleware` | Function | Auth middleware |
|
|
391
|
+
| `withInAIAuth` | Function | Compose middleware |
|
|
392
|
+
| `createRouteMatcher` | Function | Route pattern matcher |
|
|
393
|
+
|
|
394
|
+
## Exported Types
|
|
395
|
+
|
|
396
|
+
```ts
|
|
397
|
+
import type {
|
|
398
|
+
AuthObject,
|
|
399
|
+
ServerAuthObject,
|
|
400
|
+
ProtectedAuthObject,
|
|
401
|
+
UserResource,
|
|
402
|
+
PlatformUserResource,
|
|
403
|
+
SessionResource,
|
|
404
|
+
OrganizationResource,
|
|
405
|
+
InAIAuthConfig,
|
|
406
|
+
InAIAuthErrorBody,
|
|
407
|
+
SignInResult,
|
|
408
|
+
SignUpResult,
|
|
409
|
+
} from "@inai-dev/nextjs";
|
|
410
|
+
|
|
411
|
+
import type {
|
|
412
|
+
InAIMiddlewareConfig,
|
|
413
|
+
} from "@inai-dev/nextjs/middleware";
|
|
414
|
+
```
|
|
77
415
|
|
|
78
416
|
## License
|
|
79
417
|
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Re-export all React hooks, components, and providers\nexport {\n InAIAuthProvider,\n useAuth,\n useUser,\n useSession,\n useOrganization,\n useSignIn,\n useSignUp,\n Protect,\n SignedIn,\n SignedOut,\n PermissionGate,\n UserButton,\n SignIn,\n OrganizationSwitcher,\n} from \"@inai-dev/react\";\n\n// Cookie constants\nexport {\n COOKIE_AUTH_TOKEN,\n COOKIE_REFRESH_TOKEN,\n COOKIE_AUTH_SESSION,\n} from \"@inai-dev/shared\";\n\n// Re-export types\nexport type {\n AuthObject,\n ServerAuthObject,\n ProtectedAuthObject,\n UserResource,\n SessionResource,\n OrganizationResource,\n InAIAuthConfig,\n InAIAuthErrorBody,\n SignInResult,\n SignUpResult,\n} from \"@inai-dev/types\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAeO;AAGP,oBAIO;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Re-export all React hooks, components, and providers\nexport {\n InAIAuthProvider,\n useAuth,\n useUser,\n useSession,\n useOrganization,\n useSignIn,\n useSignUp,\n Protect,\n SignedIn,\n SignedOut,\n PermissionGate,\n UserButton,\n SignIn,\n OrganizationSwitcher,\n} from \"@inai-dev/react\";\n\n// Cookie constants\nexport {\n COOKIE_AUTH_TOKEN,\n COOKIE_REFRESH_TOKEN,\n COOKIE_AUTH_SESSION,\n} from \"@inai-dev/shared\";\n\n// Re-export types\nexport type {\n AuthObject,\n ServerAuthObject,\n ProtectedAuthObject,\n UserResource,\n PlatformUserResource,\n SessionResource,\n OrganizationResource,\n InAIAuthConfig,\n InAIAuthErrorBody,\n SignInResult,\n SignUpResult,\n} from \"@inai-dev/types\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAeO;AAGP,oBAIO;","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { InAIAuthProvider, OrganizationSwitcher, PermissionGate, Protect, SignIn, SignedIn, SignedOut, UserButton, useAuth, useOrganization, useSession, useSignIn, useSignUp, useUser } from '@inai-dev/react';
|
|
2
2
|
export { COOKIE_AUTH_SESSION, COOKIE_AUTH_TOKEN, COOKIE_REFRESH_TOKEN } from '@inai-dev/shared';
|
|
3
|
-
export { AuthObject, InAIAuthConfig, InAIAuthErrorBody, OrganizationResource, ProtectedAuthObject, ServerAuthObject, SessionResource, SignInResult, SignUpResult, UserResource } from '@inai-dev/types';
|
|
3
|
+
export { AuthObject, InAIAuthConfig, InAIAuthErrorBody, OrganizationResource, PlatformUserResource, ProtectedAuthObject, ServerAuthObject, SessionResource, SignInResult, SignUpResult, UserResource } from '@inai-dev/types';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { InAIAuthProvider, OrganizationSwitcher, PermissionGate, Protect, SignIn, SignedIn, SignedOut, UserButton, useAuth, useOrganization, useSession, useSignIn, useSignUp, useUser } from '@inai-dev/react';
|
|
2
2
|
export { COOKIE_AUTH_SESSION, COOKIE_AUTH_TOKEN, COOKIE_REFRESH_TOKEN } from '@inai-dev/shared';
|
|
3
|
-
export { AuthObject, InAIAuthConfig, InAIAuthErrorBody, OrganizationResource, ProtectedAuthObject, ServerAuthObject, SessionResource, SignInResult, SignUpResult, UserResource } from '@inai-dev/types';
|
|
3
|
+
export { AuthObject, InAIAuthConfig, InAIAuthErrorBody, OrganizationResource, PlatformUserResource, ProtectedAuthObject, ServerAuthObject, SessionResource, SignInResult, SignUpResult, UserResource } from '@inai-dev/types';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Re-export all React hooks, components, and providers\nexport {\n InAIAuthProvider,\n useAuth,\n useUser,\n useSession,\n useOrganization,\n useSignIn,\n useSignUp,\n Protect,\n SignedIn,\n SignedOut,\n PermissionGate,\n UserButton,\n SignIn,\n OrganizationSwitcher,\n} from \"@inai-dev/react\";\n\n// Cookie constants\nexport {\n COOKIE_AUTH_TOKEN,\n COOKIE_REFRESH_TOKEN,\n COOKIE_AUTH_SESSION,\n} from \"@inai-dev/shared\";\n\n// Re-export types\nexport type {\n AuthObject,\n ServerAuthObject,\n ProtectedAuthObject,\n UserResource,\n SessionResource,\n OrganizationResource,\n InAIAuthConfig,\n InAIAuthErrorBody,\n SignInResult,\n SignUpResult,\n} from \"@inai-dev/types\";\n"],"mappings":";;;AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Re-export all React hooks, components, and providers\nexport {\n InAIAuthProvider,\n useAuth,\n useUser,\n useSession,\n useOrganization,\n useSignIn,\n useSignUp,\n Protect,\n SignedIn,\n SignedOut,\n PermissionGate,\n UserButton,\n SignIn,\n OrganizationSwitcher,\n} from \"@inai-dev/react\";\n\n// Cookie constants\nexport {\n COOKIE_AUTH_TOKEN,\n COOKIE_REFRESH_TOKEN,\n COOKIE_AUTH_SESSION,\n} from \"@inai-dev/shared\";\n\n// Re-export types\nexport type {\n AuthObject,\n ServerAuthObject,\n ProtectedAuthObject,\n UserResource,\n PlatformUserResource,\n SessionResource,\n OrganizationResource,\n InAIAuthConfig,\n InAIAuthErrorBody,\n SignInResult,\n SignUpResult,\n} from \"@inai-dev/types\";\n"],"mappings":";;;AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
|
package/dist/middleware.cjs
CHANGED
|
@@ -75,28 +75,73 @@ function buildAuthObject(token, claims) {
|
|
|
75
75
|
}
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
|
-
async function runAuthCheck(req, signInUrl) {
|
|
78
|
+
async function runAuthCheck(req, signInUrl, apiUrl) {
|
|
79
79
|
const { pathname } = req.nextUrl;
|
|
80
80
|
const token = req.cookies.get(import_shared.COOKIE_AUTH_TOKEN)?.value;
|
|
81
81
|
if (!token || (0, import_shared.isTokenExpired)(token)) {
|
|
82
82
|
const refreshToken = req.cookies.get(import_shared.COOKIE_REFRESH_TOKEN)?.value;
|
|
83
83
|
if (refreshToken) {
|
|
84
84
|
try {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
85
|
+
if (apiUrl) {
|
|
86
|
+
const refreshRes = await fetch(`${apiUrl}/api/platform/auth/refresh`, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: { "Content-Type": "application/json" },
|
|
89
|
+
body: JSON.stringify({ refresh_token: refreshToken })
|
|
90
|
+
});
|
|
91
|
+
if (refreshRes.ok) {
|
|
92
|
+
const newTokens = await refreshRes.json();
|
|
93
|
+
const meRes = await fetch(`${apiUrl}/api/platform/auth/me`, {
|
|
94
|
+
headers: { Authorization: `Bearer ${newTokens.access_token}` }
|
|
95
|
+
});
|
|
96
|
+
if (meRes.ok) {
|
|
97
|
+
const meData = await meRes.json();
|
|
98
|
+
const newUser = meData.data ?? meData;
|
|
99
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
100
|
+
const response2 = import_server.NextResponse.next();
|
|
101
|
+
response2.cookies.set(import_shared.COOKIE_AUTH_TOKEN, newTokens.access_token, {
|
|
102
|
+
httpOnly: true,
|
|
103
|
+
secure: isProduction,
|
|
104
|
+
sameSite: "lax",
|
|
105
|
+
path: "/",
|
|
106
|
+
maxAge: newTokens.expires_in
|
|
107
|
+
});
|
|
108
|
+
response2.cookies.set(import_shared.COOKIE_REFRESH_TOKEN, newTokens.refresh_token, {
|
|
109
|
+
httpOnly: true,
|
|
110
|
+
secure: isProduction,
|
|
111
|
+
sameSite: "strict",
|
|
112
|
+
path: "/api/auth",
|
|
113
|
+
maxAge: 7 * 24 * 60 * 60
|
|
114
|
+
});
|
|
115
|
+
response2.cookies.set(import_shared.COOKIE_AUTH_SESSION, JSON.stringify({
|
|
116
|
+
user: newUser,
|
|
117
|
+
expiresAt: new Date(Date.now() + newTokens.expires_in * 1e3).toISOString()
|
|
118
|
+
}), {
|
|
119
|
+
httpOnly: false,
|
|
120
|
+
secure: isProduction,
|
|
121
|
+
sameSite: "lax",
|
|
122
|
+
path: "/",
|
|
123
|
+
maxAge: newTokens.expires_in
|
|
124
|
+
});
|
|
125
|
+
return { authObj: null, response: response2 };
|
|
126
|
+
}
|
|
91
127
|
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
128
|
+
} else {
|
|
129
|
+
const refreshUrl = new URL("/api/auth/refresh", req.url);
|
|
130
|
+
const refreshRes = await fetch(refreshUrl.toString(), {
|
|
131
|
+
method: "POST",
|
|
132
|
+
headers: {
|
|
133
|
+
"Content-Type": "application/json",
|
|
134
|
+
Cookie: req.headers.get("cookie") ?? ""
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
if (refreshRes.ok) {
|
|
138
|
+
const response2 = import_server.NextResponse.next();
|
|
139
|
+
const setCookies = refreshRes.headers.getSetCookie?.() ?? [];
|
|
140
|
+
for (const cookie of setCookies) {
|
|
141
|
+
response2.headers.append("Set-Cookie", cookie);
|
|
142
|
+
}
|
|
143
|
+
return { authObj: null, response: response2 };
|
|
98
144
|
}
|
|
99
|
-
return { authObj: null, response: response2 };
|
|
100
145
|
}
|
|
101
146
|
} catch {
|
|
102
147
|
}
|
|
@@ -126,6 +171,7 @@ async function runAuthCheck(req, signInUrl) {
|
|
|
126
171
|
}
|
|
127
172
|
function inaiAuthMiddleware(config = {}) {
|
|
128
173
|
const {
|
|
174
|
+
apiUrl = import_shared.DEFAULT_API_URL,
|
|
129
175
|
publicRoutes = [],
|
|
130
176
|
signInUrl = "/login",
|
|
131
177
|
beforeAuth,
|
|
@@ -140,7 +186,7 @@ function inaiAuthMiddleware(config = {}) {
|
|
|
140
186
|
if (isPublicRoute(req, publicRoutes, builtinPublic)) {
|
|
141
187
|
return import_server.NextResponse.next();
|
|
142
188
|
}
|
|
143
|
-
const { authObj, response } = await runAuthCheck(req, signInUrl);
|
|
189
|
+
const { authObj, response } = await runAuthCheck(req, signInUrl, apiUrl);
|
|
144
190
|
if (response) return response;
|
|
145
191
|
if (!authObj)
|
|
146
192
|
return import_server.NextResponse.redirect(new URL(signInUrl, req.url));
|
|
@@ -153,6 +199,7 @@ function inaiAuthMiddleware(config = {}) {
|
|
|
153
199
|
}
|
|
154
200
|
function withInAIAuth(wrappedMiddleware, config = {}) {
|
|
155
201
|
const {
|
|
202
|
+
apiUrl = import_shared.DEFAULT_API_URL,
|
|
156
203
|
publicRoutes = [],
|
|
157
204
|
signInUrl = "/login",
|
|
158
205
|
beforeAuth,
|
|
@@ -166,7 +213,7 @@ function withInAIAuth(wrappedMiddleware, config = {}) {
|
|
|
166
213
|
}
|
|
167
214
|
const isPublic = isPublicRoute(req, publicRoutes, builtinPublic);
|
|
168
215
|
if (!isPublic) {
|
|
169
|
-
const { authObj, response } = await runAuthCheck(req, signInUrl);
|
|
216
|
+
const { authObj, response } = await runAuthCheck(req, signInUrl, apiUrl);
|
|
170
217
|
if (response) return response;
|
|
171
218
|
if (!authObj)
|
|
172
219
|
return import_server.NextResponse.redirect(new URL(signInUrl, req.url));
|
package/dist/middleware.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/middleware.ts"],"sourcesContent":["import { NextResponse } from \"next/server\";\nimport type { NextRequest } from \"next/server\";\nimport type { AuthObject } from \"@inai-dev/types\";\nimport {\n COOKIE_AUTH_TOKEN,\n COOKIE_AUTH_SESSION,\n COOKIE_REFRESH_TOKEN,\n getClaimsFromToken,\n isTokenExpired,\n} from \"@inai-dev/shared\";\n\nexport interface InAIMiddlewareConfig {\n publicRoutes?: string[] | ((req: NextRequest) => boolean);\n signInUrl?: string;\n beforeAuth?: (req: NextRequest) => NextResponse | void;\n afterAuth?: (auth: AuthObject, req: NextRequest) => NextResponse | void;\n}\n\nexport function createRouteMatcher(\n patterns: (string | RegExp)[],\n): (req: NextRequest) => boolean {\n const matchers = patterns.map((pattern) => {\n if (pattern instanceof RegExp) return pattern;\n let regexStr = pattern;\n if (regexStr.endsWith(\"*\") && !regexStr.includes(\"(\")) {\n regexStr = regexStr.slice(0, -1) + \".*\";\n }\n return new RegExp(`^${regexStr}$`);\n });\n\n return (req: NextRequest) => {\n const pathname = req.nextUrl.pathname;\n return matchers.some((m) => m.test(pathname));\n };\n}\n\nfunction matchesRoute(pathname: string, patterns: string[]): boolean {\n return patterns.some((pattern) => {\n if (pattern.endsWith(\"*\")) {\n return pathname.startsWith(pattern.slice(0, -1));\n }\n return pathname === pattern;\n });\n}\n\nfunction isPublicRoute(\n req: NextRequest,\n publicRoutes: string[] | ((req: NextRequest) => boolean),\n builtinPublic: string[],\n): boolean {\n const pathname = req.nextUrl.pathname;\n if (matchesRoute(pathname, builtinPublic)) return true;\n if (typeof publicRoutes === \"function\") return publicRoutes(req);\n return matchesRoute(pathname, publicRoutes);\n}\n\nfunction buildAuthObject(\n token: string,\n claims: NonNullable<ReturnType<typeof getClaimsFromToken>>,\n): AuthObject {\n const roles = claims.roles ?? [];\n const permissions = claims.permissions ?? [];\n return {\n userId: claims.sub,\n tenantId: claims.tenant_id,\n appId: claims.app_id ?? null,\n envId: claims.env_id ?? null,\n orgId: claims.org_id ?? null,\n orgRole: claims.org_role ?? null,\n sessionId: null,\n getToken: async () => token,\n has: (params: { role?: string; permission?: string }) => {\n if (params.role && roles.includes(params.role)) return true;\n if (params.permission && permissions.includes(params.permission))\n return true;\n return false;\n },\n };\n}\n\nasync function runAuthCheck(\n req: NextRequest,\n signInUrl: string,\n): Promise<{ authObj: AuthObject | null; response?: NextResponse }> {\n const { pathname } = req.nextUrl;\n const token = req.cookies.get(COOKIE_AUTH_TOKEN)?.value;\n\n if (!token || isTokenExpired(token)) {\n const refreshToken = req.cookies.get(COOKIE_REFRESH_TOKEN)?.value;\n if (refreshToken) {\n try {\n const refreshUrl = new URL(\"/api/auth/refresh\", req.url);\n const refreshRes = await fetch(refreshUrl.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Cookie: req.headers.get(\"cookie\") ?? \"\",\n },\n });\n if (refreshRes.ok) {\n const response = NextResponse.next();\n const setCookies = refreshRes.headers.getSetCookie?.() ?? [];\n for (const cookie of setCookies) {\n response.headers.append(\"Set-Cookie\", cookie);\n }\n return { authObj: null, response };\n }\n } catch {\n // Refresh failed, fall through to redirect\n }\n }\n\n const response = NextResponse.redirect(\n new URL(\n `${signInUrl}?returnTo=${encodeURIComponent(pathname)}`,\n req.url,\n ),\n );\n response.cookies.set(COOKIE_AUTH_TOKEN, \"\", { path: \"/\", maxAge: 0 });\n response.cookies.set(COOKIE_REFRESH_TOKEN, \"\", {\n path: \"/api/auth\",\n maxAge: 0,\n });\n response.cookies.set(COOKIE_AUTH_SESSION, \"\", { path: \"/\", maxAge: 0 });\n return { authObj: null, response };\n }\n\n const claims = getClaimsFromToken(token);\n if (!claims) {\n return {\n authObj: null,\n response: NextResponse.redirect(new URL(signInUrl, req.url)),\n };\n }\n\n return { authObj: buildAuthObject(token, claims) };\n}\n\nexport function inaiAuthMiddleware(config: InAIMiddlewareConfig = {}) {\n const {\n publicRoutes = [],\n signInUrl = \"/login\",\n beforeAuth,\n afterAuth,\n } = config;\n\n const builtinPublic = [\"/_next/*\", \"/favicon.ico\", \"/api/*\", signInUrl];\n\n return async function middleware(\n req: NextRequest,\n ): Promise<NextResponse> {\n if (beforeAuth) {\n const result = beforeAuth(req);\n if (result) return result;\n }\n\n if (isPublicRoute(req, publicRoutes, builtinPublic)) {\n return NextResponse.next();\n }\n\n const { authObj, response } = await runAuthCheck(req, signInUrl);\n if (response) return response;\n if (!authObj)\n return NextResponse.redirect(new URL(signInUrl, req.url));\n\n if (afterAuth) {\n const result = afterAuth(authObj, req);\n if (result) return result;\n }\n\n return NextResponse.next();\n };\n}\n\nexport function withInAIAuth(\n wrappedMiddleware: (\n req: NextRequest,\n ) => NextResponse | Response | Promise<NextResponse | Response>,\n config: InAIMiddlewareConfig = {},\n): (req: NextRequest) => Promise<NextResponse> {\n const {\n publicRoutes = [],\n signInUrl = \"/login\",\n beforeAuth,\n afterAuth,\n } = config;\n\n const builtinPublic = [\"/_next/*\", \"/favicon.ico\", \"/api/*\", signInUrl];\n\n return async function middleware(\n req: NextRequest,\n ): Promise<NextResponse> {\n if (beforeAuth) {\n const result = beforeAuth(req);\n if (result) return result;\n }\n\n const isPublic = isPublicRoute(req, publicRoutes, builtinPublic);\n\n if (!isPublic) {\n const { authObj, response } = await runAuthCheck(req, signInUrl);\n if (response) return response;\n if (!authObj)\n return NextResponse.redirect(new URL(signInUrl, req.url));\n\n if (afterAuth) {\n const result = afterAuth(authObj, req);\n if (result) return result;\n }\n\n const authHeader = JSON.stringify({\n userId: authObj.userId,\n tenantId: authObj.tenantId,\n appId: authObj.appId,\n envId: authObj.envId,\n orgId: authObj.orgId,\n orgRole: authObj.orgRole,\n });\n req.headers.set(\"x-inai-auth\", authHeader);\n }\n\n const wrappedResponse = await wrappedMiddleware(req);\n if (wrappedResponse instanceof NextResponse) return wrappedResponse;\n return new NextResponse(wrappedResponse.body, wrappedResponse);\n };\n}\n"],"mappings":"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","names":["response"]}
|
|
1
|
+
{"version":3,"sources":["../src/middleware.ts"],"sourcesContent":["import { NextResponse } from \"next/server\";\nimport type { NextRequest } from \"next/server\";\nimport type { AuthObject } from \"@inai-dev/types\";\nimport {\n COOKIE_AUTH_TOKEN,\n COOKIE_AUTH_SESSION,\n COOKIE_REFRESH_TOKEN,\n DEFAULT_API_URL,\n getClaimsFromToken,\n isTokenExpired,\n} from \"@inai-dev/shared\";\n\nexport interface InAIMiddlewareConfig {\n apiUrl?: string;\n publicRoutes?: string[] | ((req: NextRequest) => boolean);\n signInUrl?: string;\n beforeAuth?: (req: NextRequest) => NextResponse | void;\n afterAuth?: (auth: AuthObject, req: NextRequest) => NextResponse | void;\n}\n\nexport function createRouteMatcher(\n patterns: (string | RegExp)[],\n): (req: NextRequest) => boolean {\n const matchers = patterns.map((pattern) => {\n if (pattern instanceof RegExp) return pattern;\n let regexStr = pattern;\n if (regexStr.endsWith(\"*\") && !regexStr.includes(\"(\")) {\n regexStr = regexStr.slice(0, -1) + \".*\";\n }\n return new RegExp(`^${regexStr}$`);\n });\n\n return (req: NextRequest) => {\n const pathname = req.nextUrl.pathname;\n return matchers.some((m) => m.test(pathname));\n };\n}\n\nfunction matchesRoute(pathname: string, patterns: string[]): boolean {\n return patterns.some((pattern) => {\n if (pattern.endsWith(\"*\")) {\n return pathname.startsWith(pattern.slice(0, -1));\n }\n return pathname === pattern;\n });\n}\n\nfunction isPublicRoute(\n req: NextRequest,\n publicRoutes: string[] | ((req: NextRequest) => boolean),\n builtinPublic: string[],\n): boolean {\n const pathname = req.nextUrl.pathname;\n if (matchesRoute(pathname, builtinPublic)) return true;\n if (typeof publicRoutes === \"function\") return publicRoutes(req);\n return matchesRoute(pathname, publicRoutes);\n}\n\nfunction buildAuthObject(\n token: string,\n claims: NonNullable<ReturnType<typeof getClaimsFromToken>>,\n): AuthObject {\n const roles = claims.roles ?? [];\n const permissions = claims.permissions ?? [];\n return {\n userId: claims.sub,\n tenantId: claims.tenant_id,\n appId: claims.app_id ?? null,\n envId: claims.env_id ?? null,\n orgId: claims.org_id ?? null,\n orgRole: claims.org_role ?? null,\n sessionId: null,\n getToken: async () => token,\n has: (params: { role?: string; permission?: string }) => {\n if (params.role && roles.includes(params.role)) return true;\n if (params.permission && permissions.includes(params.permission))\n return true;\n return false;\n },\n };\n}\n\nasync function runAuthCheck(\n req: NextRequest,\n signInUrl: string,\n apiUrl?: string,\n): Promise<{ authObj: AuthObject | null; response?: NextResponse }> {\n const { pathname } = req.nextUrl;\n const token = req.cookies.get(COOKIE_AUTH_TOKEN)?.value;\n\n if (!token || isTokenExpired(token)) {\n const refreshToken = req.cookies.get(COOKIE_REFRESH_TOKEN)?.value;\n if (refreshToken) {\n try {\n if (apiUrl) {\n const refreshRes = await fetch(`${apiUrl}/api/platform/auth/refresh`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refresh_token: refreshToken }),\n });\n if (refreshRes.ok) {\n const newTokens = await refreshRes.json() as {\n access_token: string;\n refresh_token: string;\n expires_in: number;\n };\n const meRes = await fetch(`${apiUrl}/api/platform/auth/me`, {\n headers: { Authorization: `Bearer ${newTokens.access_token}` },\n });\n if (meRes.ok) {\n const meData = await meRes.json();\n const newUser = meData.data ?? meData;\n const isProduction = process.env.NODE_ENV === \"production\";\n const response = NextResponse.next();\n response.cookies.set(COOKIE_AUTH_TOKEN, newTokens.access_token, {\n httpOnly: true, secure: isProduction, sameSite: \"lax\",\n path: \"/\", maxAge: newTokens.expires_in,\n });\n response.cookies.set(COOKIE_REFRESH_TOKEN, newTokens.refresh_token, {\n httpOnly: true, secure: isProduction, sameSite: \"strict\",\n path: \"/api/auth\", maxAge: 7 * 24 * 60 * 60,\n });\n response.cookies.set(COOKIE_AUTH_SESSION, JSON.stringify({\n user: newUser,\n expiresAt: new Date(Date.now() + newTokens.expires_in * 1000).toISOString(),\n }), {\n httpOnly: false, secure: isProduction, sameSite: \"lax\",\n path: \"/\", maxAge: newTokens.expires_in,\n });\n return { authObj: null, response };\n }\n }\n } else {\n const refreshUrl = new URL(\"/api/auth/refresh\", req.url);\n const refreshRes = await fetch(refreshUrl.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Cookie: req.headers.get(\"cookie\") ?? \"\",\n },\n });\n if (refreshRes.ok) {\n const response = NextResponse.next();\n const setCookies = refreshRes.headers.getSetCookie?.() ?? [];\n for (const cookie of setCookies) {\n response.headers.append(\"Set-Cookie\", cookie);\n }\n return { authObj: null, response };\n }\n }\n } catch {\n // Refresh failed, fall through to redirect\n }\n }\n\n const response = NextResponse.redirect(\n new URL(\n `${signInUrl}?returnTo=${encodeURIComponent(pathname)}`,\n req.url,\n ),\n );\n response.cookies.set(COOKIE_AUTH_TOKEN, \"\", { path: \"/\", maxAge: 0 });\n response.cookies.set(COOKIE_REFRESH_TOKEN, \"\", {\n path: \"/api/auth\",\n maxAge: 0,\n });\n response.cookies.set(COOKIE_AUTH_SESSION, \"\", { path: \"/\", maxAge: 0 });\n return { authObj: null, response };\n }\n\n const claims = getClaimsFromToken(token);\n if (!claims) {\n return {\n authObj: null,\n response: NextResponse.redirect(new URL(signInUrl, req.url)),\n };\n }\n\n return { authObj: buildAuthObject(token, claims) };\n}\n\nexport function inaiAuthMiddleware(config: InAIMiddlewareConfig = {}) {\n const {\n apiUrl = DEFAULT_API_URL,\n publicRoutes = [],\n signInUrl = \"/login\",\n beforeAuth,\n afterAuth,\n } = config;\n\n const builtinPublic = [\"/_next/*\", \"/favicon.ico\", \"/api/*\", signInUrl];\n\n return async function middleware(\n req: NextRequest,\n ): Promise<NextResponse> {\n if (beforeAuth) {\n const result = beforeAuth(req);\n if (result) return result;\n }\n\n if (isPublicRoute(req, publicRoutes, builtinPublic)) {\n return NextResponse.next();\n }\n\n const { authObj, response } = await runAuthCheck(req, signInUrl, apiUrl);\n if (response) return response;\n if (!authObj)\n return NextResponse.redirect(new URL(signInUrl, req.url));\n\n if (afterAuth) {\n const result = afterAuth(authObj, req);\n if (result) return result;\n }\n\n return NextResponse.next();\n };\n}\n\nexport function withInAIAuth(\n wrappedMiddleware: (\n req: NextRequest,\n ) => NextResponse | Response | Promise<NextResponse | Response>,\n config: InAIMiddlewareConfig = {},\n): (req: NextRequest) => Promise<NextResponse> {\n const {\n apiUrl = DEFAULT_API_URL,\n publicRoutes = [],\n signInUrl = \"/login\",\n beforeAuth,\n afterAuth,\n } = config;\n\n const builtinPublic = [\"/_next/*\", \"/favicon.ico\", \"/api/*\", signInUrl];\n\n return async function middleware(\n req: NextRequest,\n ): Promise<NextResponse> {\n if (beforeAuth) {\n const result = beforeAuth(req);\n if (result) return result;\n }\n\n const isPublic = isPublicRoute(req, publicRoutes, builtinPublic);\n\n if (!isPublic) {\n const { authObj, response } = await runAuthCheck(req, signInUrl, apiUrl);\n if (response) return response;\n if (!authObj)\n return NextResponse.redirect(new URL(signInUrl, req.url));\n\n if (afterAuth) {\n const result = afterAuth(authObj, req);\n if (result) return result;\n }\n\n const authHeader = JSON.stringify({\n userId: authObj.userId,\n tenantId: authObj.tenantId,\n appId: authObj.appId,\n envId: authObj.envId,\n orgId: authObj.orgId,\n orgRole: authObj.orgRole,\n });\n req.headers.set(\"x-inai-auth\", authHeader);\n }\n\n const wrappedResponse = await wrappedMiddleware(req);\n if (wrappedResponse instanceof NextResponse) return wrappedResponse;\n return new NextResponse(wrappedResponse.body, wrappedResponse);\n };\n}\n"],"mappings":"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","names":["response"]}
|
package/dist/middleware.d.cts
CHANGED
|
@@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
|
|
2
2
|
import { AuthObject } from '@inai-dev/types';
|
|
3
3
|
|
|
4
4
|
interface InAIMiddlewareConfig {
|
|
5
|
+
apiUrl?: string;
|
|
5
6
|
publicRoutes?: string[] | ((req: NextRequest) => boolean);
|
|
6
7
|
signInUrl?: string;
|
|
7
8
|
beforeAuth?: (req: NextRequest) => NextResponse | void;
|
package/dist/middleware.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
|
|
2
2
|
import { AuthObject } from '@inai-dev/types';
|
|
3
3
|
|
|
4
4
|
interface InAIMiddlewareConfig {
|
|
5
|
+
apiUrl?: string;
|
|
5
6
|
publicRoutes?: string[] | ((req: NextRequest) => boolean);
|
|
6
7
|
signInUrl?: string;
|
|
7
8
|
beforeAuth?: (req: NextRequest) => NextResponse | void;
|