@insforge/nextjs 0.8.8 → 0.8.9
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 +7 -41
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +12 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +16 -19
- package/dist/index.mjs.map +1 -1
- package/dist/middleware.js +19 -10
- package/dist/middleware.js.map +1 -1
- package/dist/middleware.mjs +19 -10
- package/dist/middleware.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -68,22 +68,7 @@ export const DELETE = handlers.DELETE;
|
|
|
68
68
|
- `GET /api/auth` - Retrieves user data server-side
|
|
69
69
|
- `DELETE /api/auth` - Clears auth cookie on sign out
|
|
70
70
|
|
|
71
|
-
### 3.
|
|
72
|
-
|
|
73
|
-
Handle OAuth redirects with the `<InsforgeCallback>` component:
|
|
74
|
-
|
|
75
|
-
```tsx
|
|
76
|
-
// app/auth/callback/page.tsx
|
|
77
|
-
'use client';
|
|
78
|
-
|
|
79
|
-
import { InsforgeCallback } from '@insforge/nextjs';
|
|
80
|
-
|
|
81
|
-
export default function CallbackPage() {
|
|
82
|
-
return <InsforgeCallback />;
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### 4. Setup Middleware
|
|
71
|
+
### 3. Setup Middleware
|
|
87
72
|
|
|
88
73
|
Protect routes with middleware:
|
|
89
74
|
|
|
@@ -107,7 +92,7 @@ export const config = {
|
|
|
107
92
|
- Verifies tokens server-side
|
|
108
93
|
- Allows public routes without auth
|
|
109
94
|
|
|
110
|
-
###
|
|
95
|
+
### 4. Use Hooks & Components
|
|
111
96
|
|
|
112
97
|
```tsx
|
|
113
98
|
// app/page.tsx
|
|
@@ -153,13 +138,12 @@ function Component() {
|
|
|
153
138
|
↓
|
|
154
139
|
2. User signs in on backend (https://your-project.insforge.app/auth/sign-in)
|
|
155
140
|
↓
|
|
156
|
-
3. Backend redirects: yourapp.com
|
|
141
|
+
3. Backend redirects: yourapp.com?access_token=xxx&user_id=xxx...
|
|
157
142
|
↓
|
|
158
|
-
4.
|
|
159
|
-
-
|
|
160
|
-
-
|
|
161
|
-
-
|
|
162
|
-
- Redirects to destination
|
|
143
|
+
4. SDK auto-detects URL parameters:
|
|
144
|
+
- Stores token in localStorage
|
|
145
|
+
- Provider automatically reloads auth state
|
|
146
|
+
- Token syncs to HTTP-only cookie (via API route)
|
|
163
147
|
↓
|
|
164
148
|
5. User sees dashboard with authenticated state
|
|
165
149
|
```
|
|
@@ -421,24 +405,6 @@ import { Protect } from '@insforge/nextjs';
|
|
|
421
405
|
</Protect>
|
|
422
406
|
```
|
|
423
407
|
|
|
424
|
-
### InsforgeCallback Options
|
|
425
|
-
|
|
426
|
-
```tsx
|
|
427
|
-
<InsforgeCallback
|
|
428
|
-
redirectTo="/dashboard"
|
|
429
|
-
onSuccess={() => console.log('Authentication successful!')}
|
|
430
|
-
onError={(error) => console.error('Authentication failed:', error)}
|
|
431
|
-
loadingComponent={
|
|
432
|
-
<div className="flex items-center justify-center min-h-screen">
|
|
433
|
-
<div className="text-center">
|
|
434
|
-
<h2 className="text-2xl font-semibold mb-4">Signing you in...</h2>
|
|
435
|
-
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto"></div>
|
|
436
|
-
</div>
|
|
437
|
-
</div>
|
|
438
|
-
}
|
|
439
|
-
/>
|
|
440
|
-
```
|
|
441
|
-
|
|
442
408
|
### Auth Change Callback
|
|
443
409
|
|
|
444
410
|
Track authentication events:
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from '@insforge/react/types';
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
|
-
import { useInsforge as useInsforge$1 } from '@insforge/react';
|
|
4
|
+
import { InsforgeUser, useInsforge as useInsforge$1 } from '@insforge/react';
|
|
5
5
|
import { ClassValue } from 'clsx';
|
|
6
6
|
export * from '@insforge/react/hooks';
|
|
7
7
|
export * from '@insforge/react/components';
|
|
@@ -9,7 +9,7 @@ export * from '@insforge/react/components';
|
|
|
9
9
|
interface InsforgeProviderProps {
|
|
10
10
|
children: ReactNode;
|
|
11
11
|
baseUrl: string;
|
|
12
|
-
onAuthChange?: (user:
|
|
12
|
+
onAuthChange?: (user: InsforgeUser | null) => void;
|
|
13
13
|
}
|
|
14
14
|
declare function InsforgeProvider({ children, baseUrl, onAuthChange, }: InsforgeProviderProps): react_jsx_runtime.JSX.Element;
|
|
15
15
|
declare const useInsforge: typeof useInsforge$1;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from '@insforge/react/types';
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
|
-
import { useInsforge as useInsforge$1 } from '@insforge/react';
|
|
4
|
+
import { InsforgeUser, useInsforge as useInsforge$1 } from '@insforge/react';
|
|
5
5
|
import { ClassValue } from 'clsx';
|
|
6
6
|
export * from '@insforge/react/hooks';
|
|
7
7
|
export * from '@insforge/react/components';
|
|
@@ -9,7 +9,7 @@ export * from '@insforge/react/components';
|
|
|
9
9
|
interface InsforgeProviderProps {
|
|
10
10
|
children: ReactNode;
|
|
11
11
|
baseUrl: string;
|
|
12
|
-
onAuthChange?: (user:
|
|
12
|
+
onAuthChange?: (user: InsforgeUser | null) => void;
|
|
13
13
|
}
|
|
14
14
|
declare function InsforgeProvider({ children, baseUrl, onAuthChange, }: InsforgeProviderProps): react_jsx_runtime.JSX.Element;
|
|
15
15
|
declare const useInsforge: typeof useInsforge$1;
|
package/dist/index.js
CHANGED
|
@@ -32,9 +32,9 @@ __reExport(src_exports, require("@insforge/react/types"), module.exports);
|
|
|
32
32
|
// src/provider/InsforgeProvider.tsx
|
|
33
33
|
var import_react = require("@insforge/react");
|
|
34
34
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
35
|
-
async function
|
|
35
|
+
async function handleSignIn(token) {
|
|
36
36
|
try {
|
|
37
|
-
|
|
37
|
+
await fetch("/api/auth", {
|
|
38
38
|
method: "POST",
|
|
39
39
|
headers: {
|
|
40
40
|
"Content-Type": "application/json"
|
|
@@ -44,15 +44,11 @@ async function syncTokenToCookie(token) {
|
|
|
44
44
|
token
|
|
45
45
|
})
|
|
46
46
|
});
|
|
47
|
-
if (!response.ok) {
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
return true;
|
|
51
47
|
} catch (error) {
|
|
52
|
-
|
|
48
|
+
console.error("[InsforgeProvider] Failed to sync token to cookie:", error);
|
|
53
49
|
}
|
|
54
50
|
}
|
|
55
|
-
async function
|
|
51
|
+
async function handleSignOut() {
|
|
56
52
|
try {
|
|
57
53
|
await fetch("/api/auth", { method: "DELETE" });
|
|
58
54
|
} catch (error) {
|
|
@@ -63,16 +59,14 @@ function InsforgeProvider({
|
|
|
63
59
|
baseUrl,
|
|
64
60
|
onAuthChange
|
|
65
61
|
}) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
);
|
|
62
|
+
const providerProps = {
|
|
63
|
+
children,
|
|
64
|
+
baseUrl,
|
|
65
|
+
onAuthChange,
|
|
66
|
+
onSignIn: handleSignIn,
|
|
67
|
+
onSignOut: handleSignOut
|
|
68
|
+
};
|
|
69
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.InsforgeProvider, { ...providerProps });
|
|
76
70
|
}
|
|
77
71
|
var useInsforge = import_react.useInsforge;
|
|
78
72
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/provider/InsforgeProvider.tsx","../src/lib/utils.ts"],"sourcesContent":["export * from '@insforge/react/types';\n\n// Provider\nexport { InsforgeProvider, useInsforge } from './provider/InsforgeProvider';\nexport { cn } from './lib/utils';\n\n// Hooks\nexport * from '@insforge/react/hooks';\n\n// Components\nexport * from '@insforge/react/components';\n","'use client';\n\nimport type { ReactNode } from 'react';\nimport { InsforgeProvider as ReactInsforgeProvider, useInsforge as useReactInsforge } from '@insforge/react';\n\nexport interface InsforgeProviderProps {\n children: ReactNode;\n baseUrl: string;\n onAuthChange?: (user:
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/provider/InsforgeProvider.tsx","../src/lib/utils.ts"],"sourcesContent":["export * from '@insforge/react/types';\n\n// Provider\nexport { InsforgeProvider, useInsforge } from './provider/InsforgeProvider';\nexport { cn } from './lib/utils';\n\n// Hooks\nexport * from '@insforge/react/hooks';\n\n// Components\nexport * from '@insforge/react/components';\n","'use client';\n\nimport type { ReactNode } from 'react';\nimport { \n InsforgeProvider as ReactInsforgeProvider, \n useInsforge as useReactInsforge,\n type InsforgeUser\n} from '@insforge/react';\n\nexport interface InsforgeProviderProps {\n children: ReactNode;\n baseUrl: string;\n onAuthChange?: (user: InsforgeUser | null) => void;\n}\n\n// Extended interface for React provider that includes internal handlers\ninterface ExtendedProviderProps extends InsforgeProviderProps {\n onSignIn?: (authToken: string) => Promise<void>;\n onSignOut?: () => Promise<void>;\n}\n\n// Sync token to server-side cookie on sign in\nasync function handleSignIn(token: string): Promise<void> {\n try {\n await fetch('/api/auth', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n action: 'sync-token',\n token,\n }),\n });\n } catch (error) {\n console.error('[InsforgeProvider] Failed to sync token to cookie:', error);\n }\n}\n\n// Clear HTTP-only cookie on sign out\nasync function handleSignOut(): Promise<void> {\n try {\n await fetch('/api/auth', { method: 'DELETE' });\n } catch (error) {\n // API route doesn't exist - ignore\n }\n}\n\n/**\n * Insforge Provider for Next.js - wraps @insforge/react provider with Next.js-specific cookie sync\n * \n * Manages user authentication state and provides all necessary context to child components.\n * Automatically syncs authentication tokens to HTTP-only cookies for server-side middleware support.\n * \n * @example\n * ```tsx\n * import { InsforgeProvider } from '@insforge/nextjs';\n * \n * export default function RootLayout({ children }) {\n * return (\n * <InsforgeProvider baseUrl={process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!}>\n * {children}\n * </InsforgeProvider>\n * );\n * }\n * ```\n */\nexport function InsforgeProvider({ \n children, \n baseUrl,\n onAuthChange,\n}: InsforgeProviderProps) {\n const providerProps: ExtendedProviderProps = {\n children,\n baseUrl,\n onAuthChange,\n onSignIn: handleSignIn,\n onSignOut: handleSignOut,\n };\n\n return <ReactInsforgeProvider {...providerProps} />;\n}\n\n/**\n * Hook to access Insforge context\n * \n * Re-exports the hook from @insforge/react for convenience.\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { user, isSignedIn, signOut } = useInsforge();\n * \n * if (!isSignedIn) return <SignIn />;\n * \n * return (\n * <div>\n * <p>Welcome {user.email}</p>\n * <button onClick={signOut}>Sign Out</button>\n * </div>\n * );\n * }\n * ```\n */\nexport const useInsforge = useReactInsforge;\n","import { type ClassValue, clsx } from 'clsx';\r\nimport { twMerge } from 'tailwind-merge';\r\n\r\n/**\r\n * Utility function to merge Tailwind CSS classes with clsx\r\n * Allows users to inject custom className overrides\r\n * \r\n * @example\r\n * ```tsx\r\n * cn(\"text-base\", isDark && \"text-white\", customClassName)\r\n * ```\r\n */\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAc,kCAAd;;;ACGA,mBAIO;AAyEE;AA1DT,eAAe,aAAa,OAA8B;AACxD,MAAI;AACF,UAAM,MAAM,aAAa;AAAA,MACvB,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,QAAQ;AAAA,QACR;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,MAAM,sDAAsD,KAAK;AAAA,EAC3E;AACF;AAGA,eAAe,gBAA+B;AAC5C,MAAI;AACF,UAAM,MAAM,aAAa,EAAE,QAAQ,SAAS,CAAC;AAAA,EAC/C,SAAS,OAAO;AAAA,EAEhB;AACF;AAqBO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,gBAAuC;AAAA,IAC3C;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,WAAW;AAAA,EACb;AAEA,SAAO,4CAAC,aAAAA,kBAAA,EAAuB,GAAG,eAAe;AACnD;AAuBO,IAAM,cAAc,aAAAC;;;ACxG3B,kBAAsC;AACtC,4BAAwB;AAWjB,SAAS,MAAM,QAAsB;AAC1C,aAAO,mCAAQ,kBAAK,MAAM,CAAC;AAC7B;;;AFPA,wBAAc,kCAPd;AAUA,wBAAc,uCAVd;","names":["ReactInsforgeProvider","useReactInsforge"]}
|
package/dist/index.mjs
CHANGED
|
@@ -4,11 +4,14 @@
|
|
|
4
4
|
export * from "@insforge/react/types";
|
|
5
5
|
|
|
6
6
|
// src/provider/InsforgeProvider.tsx
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
InsforgeProvider as ReactInsforgeProvider,
|
|
9
|
+
useInsforge as useReactInsforge
|
|
10
|
+
} from "@insforge/react";
|
|
8
11
|
import { jsx } from "react/jsx-runtime";
|
|
9
|
-
async function
|
|
12
|
+
async function handleSignIn(token) {
|
|
10
13
|
try {
|
|
11
|
-
|
|
14
|
+
await fetch("/api/auth", {
|
|
12
15
|
method: "POST",
|
|
13
16
|
headers: {
|
|
14
17
|
"Content-Type": "application/json"
|
|
@@ -18,15 +21,11 @@ async function syncTokenToCookie(token) {
|
|
|
18
21
|
token
|
|
19
22
|
})
|
|
20
23
|
});
|
|
21
|
-
if (!response.ok) {
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
return true;
|
|
25
24
|
} catch (error) {
|
|
26
|
-
|
|
25
|
+
console.error("[InsforgeProvider] Failed to sync token to cookie:", error);
|
|
27
26
|
}
|
|
28
27
|
}
|
|
29
|
-
async function
|
|
28
|
+
async function handleSignOut() {
|
|
30
29
|
try {
|
|
31
30
|
await fetch("/api/auth", { method: "DELETE" });
|
|
32
31
|
} catch (error) {
|
|
@@ -37,16 +36,14 @@ function InsforgeProvider({
|
|
|
37
36
|
baseUrl,
|
|
38
37
|
onAuthChange
|
|
39
38
|
}) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
);
|
|
39
|
+
const providerProps = {
|
|
40
|
+
children,
|
|
41
|
+
baseUrl,
|
|
42
|
+
onAuthChange,
|
|
43
|
+
onSignIn: handleSignIn,
|
|
44
|
+
onSignOut: handleSignOut
|
|
45
|
+
};
|
|
46
|
+
return /* @__PURE__ */ jsx(ReactInsforgeProvider, { ...providerProps });
|
|
50
47
|
}
|
|
51
48
|
var useInsforge = useReactInsforge;
|
|
52
49
|
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/provider/InsforgeProvider.tsx","../src/lib/utils.ts"],"sourcesContent":["export * from '@insforge/react/types';\n\n// Provider\nexport { InsforgeProvider, useInsforge } from './provider/InsforgeProvider';\nexport { cn } from './lib/utils';\n\n// Hooks\nexport * from '@insforge/react/hooks';\n\n// Components\nexport * from '@insforge/react/components';\n","'use client';\n\nimport type { ReactNode } from 'react';\nimport { InsforgeProvider as ReactInsforgeProvider, useInsforge as useReactInsforge } from '@insforge/react';\n\nexport interface InsforgeProviderProps {\n children: ReactNode;\n baseUrl: string;\n onAuthChange?: (user:
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/provider/InsforgeProvider.tsx","../src/lib/utils.ts"],"sourcesContent":["export * from '@insforge/react/types';\n\n// Provider\nexport { InsforgeProvider, useInsforge } from './provider/InsforgeProvider';\nexport { cn } from './lib/utils';\n\n// Hooks\nexport * from '@insforge/react/hooks';\n\n// Components\nexport * from '@insforge/react/components';\n","'use client';\n\nimport type { ReactNode } from 'react';\nimport { \n InsforgeProvider as ReactInsforgeProvider, \n useInsforge as useReactInsforge,\n type InsforgeUser\n} from '@insforge/react';\n\nexport interface InsforgeProviderProps {\n children: ReactNode;\n baseUrl: string;\n onAuthChange?: (user: InsforgeUser | null) => void;\n}\n\n// Extended interface for React provider that includes internal handlers\ninterface ExtendedProviderProps extends InsforgeProviderProps {\n onSignIn?: (authToken: string) => Promise<void>;\n onSignOut?: () => Promise<void>;\n}\n\n// Sync token to server-side cookie on sign in\nasync function handleSignIn(token: string): Promise<void> {\n try {\n await fetch('/api/auth', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n action: 'sync-token',\n token,\n }),\n });\n } catch (error) {\n console.error('[InsforgeProvider] Failed to sync token to cookie:', error);\n }\n}\n\n// Clear HTTP-only cookie on sign out\nasync function handleSignOut(): Promise<void> {\n try {\n await fetch('/api/auth', { method: 'DELETE' });\n } catch (error) {\n // API route doesn't exist - ignore\n }\n}\n\n/**\n * Insforge Provider for Next.js - wraps @insforge/react provider with Next.js-specific cookie sync\n * \n * Manages user authentication state and provides all necessary context to child components.\n * Automatically syncs authentication tokens to HTTP-only cookies for server-side middleware support.\n * \n * @example\n * ```tsx\n * import { InsforgeProvider } from '@insforge/nextjs';\n * \n * export default function RootLayout({ children }) {\n * return (\n * <InsforgeProvider baseUrl={process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!}>\n * {children}\n * </InsforgeProvider>\n * );\n * }\n * ```\n */\nexport function InsforgeProvider({ \n children, \n baseUrl,\n onAuthChange,\n}: InsforgeProviderProps) {\n const providerProps: ExtendedProviderProps = {\n children,\n baseUrl,\n onAuthChange,\n onSignIn: handleSignIn,\n onSignOut: handleSignOut,\n };\n\n return <ReactInsforgeProvider {...providerProps} />;\n}\n\n/**\n * Hook to access Insforge context\n * \n * Re-exports the hook from @insforge/react for convenience.\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { user, isSignedIn, signOut } = useInsforge();\n * \n * if (!isSignedIn) return <SignIn />;\n * \n * return (\n * <div>\n * <p>Welcome {user.email}</p>\n * <button onClick={signOut}>Sign Out</button>\n * </div>\n * );\n * }\n * ```\n */\nexport const useInsforge = useReactInsforge;\n","import { type ClassValue, clsx } from 'clsx';\r\nimport { twMerge } from 'tailwind-merge';\r\n\r\n/**\r\n * Utility function to merge Tailwind CSS classes with clsx\r\n * Allows users to inject custom className overrides\r\n * \r\n * @example\r\n * ```tsx\r\n * cn(\"text-base\", isDark && \"text-white\", customClassName)\r\n * ```\r\n */\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n\r\n"],"mappings":";;;AAAA,cAAc;;;ACGd;AAAA,EACE,oBAAoB;AAAA,EACpB,eAAe;AAAA,OAEV;AAyEE;AA1DT,eAAe,aAAa,OAA8B;AACxD,MAAI;AACF,UAAM,MAAM,aAAa;AAAA,MACvB,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,QAAQ;AAAA,QACR;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,MAAM,sDAAsD,KAAK;AAAA,EAC3E;AACF;AAGA,eAAe,gBAA+B;AAC5C,MAAI;AACF,UAAM,MAAM,aAAa,EAAE,QAAQ,SAAS,CAAC;AAAA,EAC/C,SAAS,OAAO;AAAA,EAEhB;AACF;AAqBO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,gBAAuC;AAAA,IAC3C;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,WAAW;AAAA,EACb;AAEA,SAAO,oBAAC,yBAAuB,GAAG,eAAe;AACnD;AAuBO,IAAM,cAAc;;;ACxG3B,SAA0B,YAAY;AACtC,SAAS,eAAe;AAWjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;;;AFPA,cAAc;AAGd,cAAc;","names":[]}
|
package/dist/middleware.js
CHANGED
|
@@ -30,23 +30,33 @@ var import_server = require("next/server");
|
|
|
30
30
|
function InsforgeMiddleware(config) {
|
|
31
31
|
const {
|
|
32
32
|
baseUrl,
|
|
33
|
-
publicRoutes = ["/
|
|
33
|
+
publicRoutes = ["/"],
|
|
34
34
|
signInUrl = "/sign-in",
|
|
35
35
|
signUpUrl = "/sign-up",
|
|
36
36
|
cookieName = "insforge_token",
|
|
37
37
|
useBuiltInAuth = true
|
|
38
38
|
} = config;
|
|
39
39
|
return async function middleware(request) {
|
|
40
|
-
const { pathname } = request.nextUrl;
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
const { pathname, searchParams } = request.nextUrl;
|
|
41
|
+
const accessToken = searchParams.get("access_token");
|
|
42
|
+
if (accessToken) {
|
|
43
|
+
const response = import_server.NextResponse.redirect(new URL(pathname, request.url));
|
|
44
|
+
response.cookies.set(cookieName, accessToken, {
|
|
45
|
+
httpOnly: true,
|
|
46
|
+
secure: process.env.NODE_ENV === "production",
|
|
47
|
+
sameSite: "lax",
|
|
48
|
+
path: "/",
|
|
49
|
+
maxAge: 60 * 60 * 24 * 7
|
|
50
|
+
// 7 days
|
|
51
|
+
});
|
|
52
|
+
return response;
|
|
43
53
|
}
|
|
44
54
|
if (useBuiltInAuth && (pathname === signInUrl || pathname === signUpUrl)) {
|
|
45
|
-
const
|
|
55
|
+
const currentUrl = request.url;
|
|
46
56
|
const backendAuthPath = pathname === signInUrl ? "/auth/sign-in" : "/auth/sign-up";
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
return import_server.NextResponse.redirect(
|
|
57
|
+
const backendAuthUrl = new URL(backendAuthPath, baseUrl);
|
|
58
|
+
backendAuthUrl.searchParams.set("redirect", currentUrl);
|
|
59
|
+
return import_server.NextResponse.redirect(backendAuthUrl.toString());
|
|
50
60
|
}
|
|
51
61
|
const isPublicRoute = publicRoutes.some((route) => {
|
|
52
62
|
if (route.endsWith("*")) {
|
|
@@ -60,9 +70,8 @@ function InsforgeMiddleware(config) {
|
|
|
60
70
|
const token = request.cookies.get(cookieName)?.value;
|
|
61
71
|
if (!token) {
|
|
62
72
|
if (useBuiltInAuth) {
|
|
63
|
-
const callbackUrl = new URL("/auth/callback", request.url);
|
|
64
73
|
const backendSignInUrl = new URL("/auth/sign-in", baseUrl);
|
|
65
|
-
backendSignInUrl.searchParams.set("redirect",
|
|
74
|
+
backendSignInUrl.searchParams.set("redirect", request.url);
|
|
66
75
|
return import_server.NextResponse.redirect(backendSignInUrl);
|
|
67
76
|
} else {
|
|
68
77
|
const localSignInUrl = new URL(signInUrl, request.url);
|
package/dist/middleware.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/middleware/index.ts","../src/middleware/InsforgeMiddleware.ts"],"sourcesContent":["// Middleware exports - NO 'use client' directive here!\r\n// Middleware runs in Edge Runtime, not in client browser\r\n\r\nexport {\r\n InsforgeMiddleware,\r\n} from './InsforgeMiddleware';\r\n\r\nexport type { InsforgeMiddlewareConfig } from './InsforgeMiddleware';\r\n\r\n","import { NextRequest, NextResponse } from 'next/server';\r\n\r\nexport interface InsforgeMiddlewareConfig {\r\n /**\r\n * Base URL of your Insforge backend\r\n * @example 'https://your-backend.com' or 'http://localhost:3001'\r\n */\r\n baseUrl: string;\r\n\r\n /**\r\n * Routes that are public and don't require authentication\r\n *
|
|
1
|
+
{"version":3,"sources":["../src/middleware/index.ts","../src/middleware/InsforgeMiddleware.ts"],"sourcesContent":["// Middleware exports - NO 'use client' directive here!\r\n// Middleware runs in Edge Runtime, not in client browser\r\n\r\nexport {\r\n InsforgeMiddleware,\r\n} from './InsforgeMiddleware';\r\n\r\nexport type { InsforgeMiddlewareConfig } from './InsforgeMiddleware';\r\n\r\n","import { NextRequest, NextResponse } from 'next/server';\r\n\r\nexport interface InsforgeMiddlewareConfig {\r\n /**\r\n * Base URL of your Insforge backend\r\n * @example 'https://your-backend.com' or 'http://localhost:3001'\r\n */\r\n baseUrl: string;\r\n\r\n /**\r\n * Routes that are public and don't require authentication\r\n * @default ['/']\r\n * @example ['/sign-in', '/sign-up', '/', '/about']\r\n */\r\n publicRoutes?: string[];\r\n\r\n /**\r\n * Local route path for sign-in (can be customized to any path like '/login')\r\n * When using built-in auth, this will redirect to backend's `/auth/sign-in`\r\n * @default '/sign-in'\r\n */\r\n signInUrl?: string;\r\n\r\n /**\r\n * Local route path for sign-up (can be customized to any path like '/register')\r\n * When using built-in auth, this will redirect to backend's `/auth/sign-up`\r\n * @default '/sign-up'\r\n */\r\n signUpUrl?: string;\r\n\r\n /**\r\n * Cookie name for the auth token\r\n * @default 'insforge_token'\r\n */\r\n cookieName?: string;\r\n\r\n /**\r\n * Whether to use built-in authentication pages hosted on the backend\r\n * - When true: redirects to backend's `/auth/sign-in` and `/auth/sign-up` pages\r\n * - When false: redirects to local sign-in/sign-up pages (you provide your own components)\r\n * @default true\r\n */\r\n useBuiltInAuth?: boolean;\r\n}\r\n\r\n/**\r\n * Creates Next.js middleware for protecting routes with Insforge authentication.\r\n * \r\n * This middleware provides lightweight route protection by:\r\n * - Detecting and storing auth tokens from URL parameters (after backend redirect)\r\n * - Checking for auth token presence in cookies\r\n * - Redirecting unauthenticated users to sign-in page\r\n * - Allowing public routes to be accessed without authentication\r\n * - Mapping local auth routes to backend's fixed paths when using built-in auth\r\n * \r\n * **How Authentication Flow Works:**\r\n * 1. User visits protected route → Middleware checks for token\r\n * 2. No token → Redirects to sign-in (backend or local)\r\n * 3. After sign-in → Backend redirects to `yourapp.com/destination?access_token=xxx&user_id=xxx...`\r\n * 4. Middleware detects `access_token` in URL → Stores in HTTP-only cookie → Cleans URL → Allows access\r\n * 5. SDK also detects token from URL → Stores in localStorage → Updates auth state\r\n * \r\n * **Important Notes:**\r\n * - This middleware only checks if a token exists, it doesn't validate it\r\n * - Tokens from URL are automatically extracted and stored in cookies\r\n * - When `useBuiltInAuth: true`, local routes map to backend's `/auth/sign-in` and `/auth/sign-up`\r\n * - You can customize local route paths (e.g., `/login`) while backend paths remain fixed\r\n * \r\n * @param config - Middleware configuration\r\n * @returns Next.js middleware function\r\n *\r\n * @example\r\n * ```ts\r\n * // middleware.ts - Using built-in auth\r\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\r\n *\r\n * export default InsforgeMiddleware({\r\n * baseUrl: process.env.INSFORGE_BASE_URL!,\r\n * publicRoutes: ['/', '/about'],\r\n * useBuiltInAuth: true,\r\n * });\r\n *\r\n * export const config = {\r\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\r\n * };\r\n * ```\r\n * \r\n * @example\r\n * ```ts\r\n * // middleware.ts - Custom local auth pages with custom paths\r\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\r\n *\r\n * export default InsforgeMiddleware({\r\n * baseUrl: process.env.INSFORGE_BASE_URL!,\r\n * publicRoutes: ['/login', '/register', '/', '/about'],\r\n * signInUrl: '/login',\r\n * signUpUrl: '/register',\r\n * useBuiltInAuth: false,\r\n * });\r\n *\r\n * export const config = {\r\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\r\n * };\r\n * ```\r\n * \r\n * @example\r\n * ```ts\r\n * // middleware.ts - Built-in auth with custom local route names\r\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\r\n *\r\n * export default InsforgeMiddleware({\r\n * baseUrl: 'https://your-backend.com',\r\n * signInUrl: '/login',\r\n * signUpUrl: '/register',\r\n * useBuiltInAuth: true,\r\n * });\r\n * ```\r\n */\r\nexport function InsforgeMiddleware(config: InsforgeMiddlewareConfig) {\r\n const {\r\n baseUrl,\r\n publicRoutes = [\"/\"],\r\n signInUrl = '/sign-in',\r\n signUpUrl = '/sign-up',\r\n cookieName = 'insforge_token',\r\n useBuiltInAuth = true,\r\n } = config;\r\n\r\n return async function middleware(request: NextRequest) {\r\n const { pathname, searchParams } = request.nextUrl;\r\n\r\n // STEP 1: Check if URL contains access_token (from backend redirect after auth)\r\n const accessToken = searchParams.get('access_token');\r\n \r\n if (accessToken) {\r\n // Token detected in URL - store it in HTTP-only cookie and clean URL\r\n const response = NextResponse.redirect(new URL(pathname, request.url));\r\n \r\n // Set HTTP-only cookie with secure settings\r\n response.cookies.set(cookieName, accessToken, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'lax',\r\n path: '/',\r\n maxAge: 60 * 60 * 24 * 7, // 7 days\r\n });\r\n \r\n return response;\r\n }\r\n\r\n // STEP 2: Handle built-in auth redirects for sign-in/sign-up pages\r\n // Map local sign-in/sign-up routes to backend's fixed auth pages\r\n if (useBuiltInAuth && (pathname === signInUrl || pathname === signUpUrl)) {\r\n // Backend redirects directly to the current page with token in URL\r\n const currentUrl = request.url;\r\n const backendAuthPath = pathname === signInUrl ? '/auth/sign-in' : '/auth/sign-up';\r\n const backendAuthUrl = new URL(backendAuthPath, baseUrl);\r\n backendAuthUrl.searchParams.set('redirect', currentUrl);\r\n return NextResponse.redirect(backendAuthUrl.toString());\r\n }\r\n\r\n // STEP 3: Check if route is public\r\n const isPublicRoute = publicRoutes.some((route) => {\r\n if (route.endsWith('*')) {\r\n // Wildcard route: /admin/* matches /admin/anything\r\n return pathname.startsWith(route.slice(0, -1));\r\n }\r\n // Exact match or starts with route path\r\n return pathname === route || pathname.startsWith(route + '/');\r\n });\r\n\r\n if (isPublicRoute) {\r\n return NextResponse.next();\r\n }\r\n\r\n // STEP 4: Check for authentication token in cookies\r\n const token = request.cookies.get(cookieName)?.value;\r\n\r\n if (!token) {\r\n // No token found, redirect to sign-in\r\n if (useBuiltInAuth) {\r\n // Built-in auth: redirect to backend's /auth/sign-in page\r\n // Backend will redirect back to current URL with token\r\n const backendSignInUrl = new URL('/auth/sign-in', baseUrl);\r\n backendSignInUrl.searchParams.set('redirect', request.url);\r\n return NextResponse.redirect(backendSignInUrl);\r\n } else {\r\n // Custom auth: redirect to local sign-in page\r\n const localSignInUrl = new URL(signInUrl, request.url);\r\n localSignInUrl.searchParams.set('redirect', pathname);\r\n return NextResponse.redirect(localSignInUrl);\r\n }\r\n }\r\n\r\n // Token exists in cookie, allow request to continue\r\n return NextResponse.next();\r\n };\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAA0C;AAsHnC,SAAS,mBAAmB,QAAkC;AACnE,QAAM;AAAA,IACJ;AAAA,IACA,eAAe,CAAC,GAAG;AAAA,IACnB,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,iBAAiB;AAAA,EACnB,IAAI;AAEJ,SAAO,eAAe,WAAW,SAAsB;AACrD,UAAM,EAAE,UAAU,aAAa,IAAI,QAAQ;AAG3C,UAAM,cAAc,aAAa,IAAI,cAAc;AAEnD,QAAI,aAAa;AAEf,YAAM,WAAW,2BAAa,SAAS,IAAI,IAAI,UAAU,QAAQ,GAAG,CAAC;AAGrE,eAAS,QAAQ,IAAI,YAAY,aAAa;AAAA,QAC5C,UAAU;AAAA,QACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,QACjC,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,KAAK,KAAK,KAAK;AAAA;AAAA,MACzB,CAAC;AAED,aAAO;AAAA,IACT;AAIA,QAAI,mBAAmB,aAAa,aAAa,aAAa,YAAY;AAExE,YAAM,aAAa,QAAQ;AAC3B,YAAM,kBAAkB,aAAa,YAAY,kBAAkB;AACnE,YAAM,iBAAiB,IAAI,IAAI,iBAAiB,OAAO;AACvD,qBAAe,aAAa,IAAI,YAAY,UAAU;AACtD,aAAO,2BAAa,SAAS,eAAe,SAAS,CAAC;AAAA,IACxD;AAGA,UAAM,gBAAgB,aAAa,KAAK,CAAC,UAAU;AACjD,UAAI,MAAM,SAAS,GAAG,GAAG;AAEvB,eAAO,SAAS,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,MAC/C;AAEA,aAAO,aAAa,SAAS,SAAS,WAAW,QAAQ,GAAG;AAAA,IAC9D,CAAC;AAED,QAAI,eAAe;AACjB,aAAO,2BAAa,KAAK;AAAA,IAC3B;AAGA,UAAM,QAAQ,QAAQ,QAAQ,IAAI,UAAU,GAAG;AAE/C,QAAI,CAAC,OAAO;AAEV,UAAI,gBAAgB;AAGlB,cAAM,mBAAmB,IAAI,IAAI,iBAAiB,OAAO;AACzD,yBAAiB,aAAa,IAAI,YAAY,QAAQ,GAAG;AACzD,eAAO,2BAAa,SAAS,gBAAgB;AAAA,MAC/C,OAAO;AAEL,cAAM,iBAAiB,IAAI,IAAI,WAAW,QAAQ,GAAG;AACrD,uBAAe,aAAa,IAAI,YAAY,QAAQ;AACpD,eAAO,2BAAa,SAAS,cAAc;AAAA,MAC7C;AAAA,IACF;AAGA,WAAO,2BAAa,KAAK;AAAA,EAC3B;AACF;","names":[]}
|
package/dist/middleware.mjs
CHANGED
|
@@ -5,23 +5,33 @@ import { NextResponse } from "next/server";
|
|
|
5
5
|
function InsforgeMiddleware(config) {
|
|
6
6
|
const {
|
|
7
7
|
baseUrl,
|
|
8
|
-
publicRoutes = ["/
|
|
8
|
+
publicRoutes = ["/"],
|
|
9
9
|
signInUrl = "/sign-in",
|
|
10
10
|
signUpUrl = "/sign-up",
|
|
11
11
|
cookieName = "insforge_token",
|
|
12
12
|
useBuiltInAuth = true
|
|
13
13
|
} = config;
|
|
14
14
|
return async function middleware(request) {
|
|
15
|
-
const { pathname } = request.nextUrl;
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const { pathname, searchParams } = request.nextUrl;
|
|
16
|
+
const accessToken = searchParams.get("access_token");
|
|
17
|
+
if (accessToken) {
|
|
18
|
+
const response = NextResponse.redirect(new URL(pathname, request.url));
|
|
19
|
+
response.cookies.set(cookieName, accessToken, {
|
|
20
|
+
httpOnly: true,
|
|
21
|
+
secure: process.env.NODE_ENV === "production",
|
|
22
|
+
sameSite: "lax",
|
|
23
|
+
path: "/",
|
|
24
|
+
maxAge: 60 * 60 * 24 * 7
|
|
25
|
+
// 7 days
|
|
26
|
+
});
|
|
27
|
+
return response;
|
|
18
28
|
}
|
|
19
29
|
if (useBuiltInAuth && (pathname === signInUrl || pathname === signUpUrl)) {
|
|
20
|
-
const
|
|
30
|
+
const currentUrl = request.url;
|
|
21
31
|
const backendAuthPath = pathname === signInUrl ? "/auth/sign-in" : "/auth/sign-up";
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
return NextResponse.redirect(
|
|
32
|
+
const backendAuthUrl = new URL(backendAuthPath, baseUrl);
|
|
33
|
+
backendAuthUrl.searchParams.set("redirect", currentUrl);
|
|
34
|
+
return NextResponse.redirect(backendAuthUrl.toString());
|
|
25
35
|
}
|
|
26
36
|
const isPublicRoute = publicRoutes.some((route) => {
|
|
27
37
|
if (route.endsWith("*")) {
|
|
@@ -35,9 +45,8 @@ function InsforgeMiddleware(config) {
|
|
|
35
45
|
const token = request.cookies.get(cookieName)?.value;
|
|
36
46
|
if (!token) {
|
|
37
47
|
if (useBuiltInAuth) {
|
|
38
|
-
const callbackUrl = new URL("/auth/callback", request.url);
|
|
39
48
|
const backendSignInUrl = new URL("/auth/sign-in", baseUrl);
|
|
40
|
-
backendSignInUrl.searchParams.set("redirect",
|
|
49
|
+
backendSignInUrl.searchParams.set("redirect", request.url);
|
|
41
50
|
return NextResponse.redirect(backendSignInUrl);
|
|
42
51
|
} else {
|
|
43
52
|
const localSignInUrl = new URL(signInUrl, request.url);
|
package/dist/middleware.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/middleware/InsforgeMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\r\n\r\nexport interface InsforgeMiddlewareConfig {\r\n /**\r\n * Base URL of your Insforge backend\r\n * @example 'https://your-backend.com' or 'http://localhost:3001'\r\n */\r\n baseUrl: string;\r\n\r\n /**\r\n * Routes that are public and don't require authentication\r\n *
|
|
1
|
+
{"version":3,"sources":["../src/middleware/InsforgeMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\r\n\r\nexport interface InsforgeMiddlewareConfig {\r\n /**\r\n * Base URL of your Insforge backend\r\n * @example 'https://your-backend.com' or 'http://localhost:3001'\r\n */\r\n baseUrl: string;\r\n\r\n /**\r\n * Routes that are public and don't require authentication\r\n * @default ['/']\r\n * @example ['/sign-in', '/sign-up', '/', '/about']\r\n */\r\n publicRoutes?: string[];\r\n\r\n /**\r\n * Local route path for sign-in (can be customized to any path like '/login')\r\n * When using built-in auth, this will redirect to backend's `/auth/sign-in`\r\n * @default '/sign-in'\r\n */\r\n signInUrl?: string;\r\n\r\n /**\r\n * Local route path for sign-up (can be customized to any path like '/register')\r\n * When using built-in auth, this will redirect to backend's `/auth/sign-up`\r\n * @default '/sign-up'\r\n */\r\n signUpUrl?: string;\r\n\r\n /**\r\n * Cookie name for the auth token\r\n * @default 'insforge_token'\r\n */\r\n cookieName?: string;\r\n\r\n /**\r\n * Whether to use built-in authentication pages hosted on the backend\r\n * - When true: redirects to backend's `/auth/sign-in` and `/auth/sign-up` pages\r\n * - When false: redirects to local sign-in/sign-up pages (you provide your own components)\r\n * @default true\r\n */\r\n useBuiltInAuth?: boolean;\r\n}\r\n\r\n/**\r\n * Creates Next.js middleware for protecting routes with Insforge authentication.\r\n * \r\n * This middleware provides lightweight route protection by:\r\n * - Detecting and storing auth tokens from URL parameters (after backend redirect)\r\n * - Checking for auth token presence in cookies\r\n * - Redirecting unauthenticated users to sign-in page\r\n * - Allowing public routes to be accessed without authentication\r\n * - Mapping local auth routes to backend's fixed paths when using built-in auth\r\n * \r\n * **How Authentication Flow Works:**\r\n * 1. User visits protected route → Middleware checks for token\r\n * 2. No token → Redirects to sign-in (backend or local)\r\n * 3. After sign-in → Backend redirects to `yourapp.com/destination?access_token=xxx&user_id=xxx...`\r\n * 4. Middleware detects `access_token` in URL → Stores in HTTP-only cookie → Cleans URL → Allows access\r\n * 5. SDK also detects token from URL → Stores in localStorage → Updates auth state\r\n * \r\n * **Important Notes:**\r\n * - This middleware only checks if a token exists, it doesn't validate it\r\n * - Tokens from URL are automatically extracted and stored in cookies\r\n * - When `useBuiltInAuth: true`, local routes map to backend's `/auth/sign-in` and `/auth/sign-up`\r\n * - You can customize local route paths (e.g., `/login`) while backend paths remain fixed\r\n * \r\n * @param config - Middleware configuration\r\n * @returns Next.js middleware function\r\n *\r\n * @example\r\n * ```ts\r\n * // middleware.ts - Using built-in auth\r\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\r\n *\r\n * export default InsforgeMiddleware({\r\n * baseUrl: process.env.INSFORGE_BASE_URL!,\r\n * publicRoutes: ['/', '/about'],\r\n * useBuiltInAuth: true,\r\n * });\r\n *\r\n * export const config = {\r\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\r\n * };\r\n * ```\r\n * \r\n * @example\r\n * ```ts\r\n * // middleware.ts - Custom local auth pages with custom paths\r\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\r\n *\r\n * export default InsforgeMiddleware({\r\n * baseUrl: process.env.INSFORGE_BASE_URL!,\r\n * publicRoutes: ['/login', '/register', '/', '/about'],\r\n * signInUrl: '/login',\r\n * signUpUrl: '/register',\r\n * useBuiltInAuth: false,\r\n * });\r\n *\r\n * export const config = {\r\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\r\n * };\r\n * ```\r\n * \r\n * @example\r\n * ```ts\r\n * // middleware.ts - Built-in auth with custom local route names\r\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\r\n *\r\n * export default InsforgeMiddleware({\r\n * baseUrl: 'https://your-backend.com',\r\n * signInUrl: '/login',\r\n * signUpUrl: '/register',\r\n * useBuiltInAuth: true,\r\n * });\r\n * ```\r\n */\r\nexport function InsforgeMiddleware(config: InsforgeMiddlewareConfig) {\r\n const {\r\n baseUrl,\r\n publicRoutes = [\"/\"],\r\n signInUrl = '/sign-in',\r\n signUpUrl = '/sign-up',\r\n cookieName = 'insforge_token',\r\n useBuiltInAuth = true,\r\n } = config;\r\n\r\n return async function middleware(request: NextRequest) {\r\n const { pathname, searchParams } = request.nextUrl;\r\n\r\n // STEP 1: Check if URL contains access_token (from backend redirect after auth)\r\n const accessToken = searchParams.get('access_token');\r\n \r\n if (accessToken) {\r\n // Token detected in URL - store it in HTTP-only cookie and clean URL\r\n const response = NextResponse.redirect(new URL(pathname, request.url));\r\n \r\n // Set HTTP-only cookie with secure settings\r\n response.cookies.set(cookieName, accessToken, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'lax',\r\n path: '/',\r\n maxAge: 60 * 60 * 24 * 7, // 7 days\r\n });\r\n \r\n return response;\r\n }\r\n\r\n // STEP 2: Handle built-in auth redirects for sign-in/sign-up pages\r\n // Map local sign-in/sign-up routes to backend's fixed auth pages\r\n if (useBuiltInAuth && (pathname === signInUrl || pathname === signUpUrl)) {\r\n // Backend redirects directly to the current page with token in URL\r\n const currentUrl = request.url;\r\n const backendAuthPath = pathname === signInUrl ? '/auth/sign-in' : '/auth/sign-up';\r\n const backendAuthUrl = new URL(backendAuthPath, baseUrl);\r\n backendAuthUrl.searchParams.set('redirect', currentUrl);\r\n return NextResponse.redirect(backendAuthUrl.toString());\r\n }\r\n\r\n // STEP 3: Check if route is public\r\n const isPublicRoute = publicRoutes.some((route) => {\r\n if (route.endsWith('*')) {\r\n // Wildcard route: /admin/* matches /admin/anything\r\n return pathname.startsWith(route.slice(0, -1));\r\n }\r\n // Exact match or starts with route path\r\n return pathname === route || pathname.startsWith(route + '/');\r\n });\r\n\r\n if (isPublicRoute) {\r\n return NextResponse.next();\r\n }\r\n\r\n // STEP 4: Check for authentication token in cookies\r\n const token = request.cookies.get(cookieName)?.value;\r\n\r\n if (!token) {\r\n // No token found, redirect to sign-in\r\n if (useBuiltInAuth) {\r\n // Built-in auth: redirect to backend's /auth/sign-in page\r\n // Backend will redirect back to current URL with token\r\n const backendSignInUrl = new URL('/auth/sign-in', baseUrl);\r\n backendSignInUrl.searchParams.set('redirect', request.url);\r\n return NextResponse.redirect(backendSignInUrl);\r\n } else {\r\n // Custom auth: redirect to local sign-in page\r\n const localSignInUrl = new URL(signInUrl, request.url);\r\n localSignInUrl.searchParams.set('redirect', pathname);\r\n return NextResponse.redirect(localSignInUrl);\r\n }\r\n }\r\n\r\n // Token exists in cookie, allow request to continue\r\n return NextResponse.next();\r\n };\r\n}"],"mappings":";;;AAAA,SAAsB,oBAAoB;AAsHnC,SAAS,mBAAmB,QAAkC;AACnE,QAAM;AAAA,IACJ;AAAA,IACA,eAAe,CAAC,GAAG;AAAA,IACnB,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,iBAAiB;AAAA,EACnB,IAAI;AAEJ,SAAO,eAAe,WAAW,SAAsB;AACrD,UAAM,EAAE,UAAU,aAAa,IAAI,QAAQ;AAG3C,UAAM,cAAc,aAAa,IAAI,cAAc;AAEnD,QAAI,aAAa;AAEf,YAAM,WAAW,aAAa,SAAS,IAAI,IAAI,UAAU,QAAQ,GAAG,CAAC;AAGrE,eAAS,QAAQ,IAAI,YAAY,aAAa;AAAA,QAC5C,UAAU;AAAA,QACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,QACjC,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,KAAK,KAAK,KAAK;AAAA;AAAA,MACzB,CAAC;AAED,aAAO;AAAA,IACT;AAIA,QAAI,mBAAmB,aAAa,aAAa,aAAa,YAAY;AAExE,YAAM,aAAa,QAAQ;AAC3B,YAAM,kBAAkB,aAAa,YAAY,kBAAkB;AACnE,YAAM,iBAAiB,IAAI,IAAI,iBAAiB,OAAO;AACvD,qBAAe,aAAa,IAAI,YAAY,UAAU;AACtD,aAAO,aAAa,SAAS,eAAe,SAAS,CAAC;AAAA,IACxD;AAGA,UAAM,gBAAgB,aAAa,KAAK,CAAC,UAAU;AACjD,UAAI,MAAM,SAAS,GAAG,GAAG;AAEvB,eAAO,SAAS,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,MAC/C;AAEA,aAAO,aAAa,SAAS,SAAS,WAAW,QAAQ,GAAG;AAAA,IAC9D,CAAC;AAED,QAAI,eAAe;AACjB,aAAO,aAAa,KAAK;AAAA,IAC3B;AAGA,UAAM,QAAQ,QAAQ,QAAQ,IAAI,UAAU,GAAG;AAE/C,QAAI,CAAC,OAAO;AAEV,UAAI,gBAAgB;AAGlB,cAAM,mBAAmB,IAAI,IAAI,iBAAiB,OAAO;AACzD,yBAAiB,aAAa,IAAI,YAAY,QAAQ,GAAG;AACzD,eAAO,aAAa,SAAS,gBAAgB;AAAA,MAC/C,OAAO;AAEL,cAAM,iBAAiB,IAAI,IAAI,WAAW,QAAQ,GAAG;AACrD,uBAAe,aAAa,IAAI,YAAY,QAAQ;AACpD,eAAO,aAAa,SAAS,cAAc;AAAA,MAC7C;AAAA,IACF;AAGA,WAAO,aAAa,KAAK;AAAA,EAC3B;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@insforge/nextjs",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.9",
|
|
4
4
|
"description": "Pre-built authentication UI components for Next.js with Insforge backend - zero configuration required",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"react-dom": "^19.0.0"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@insforge/react": "^0.
|
|
53
|
+
"@insforge/react": "^0.4.5",
|
|
54
54
|
"@insforge/sdk": "0.0.58-dev.13",
|
|
55
55
|
"@insforge/shared-schemas": "^1.1.17",
|
|
56
56
|
"clsx": "^2.1.1",
|