@insforge/nextjs 0.8.6 → 0.8.8

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.
@@ -2,19 +2,12 @@ import { NextRequest, NextResponse } from 'next/server';
2
2
 
3
3
  interface InsforgeMiddlewareConfig {
4
4
  baseUrl: string;
5
- frontendUrl?: string;
6
5
  publicRoutes?: string[];
7
- afterSignInUrl?: string;
8
6
  signInUrl?: string;
9
7
  signUpUrl?: string;
10
8
  cookieName?: string;
11
9
  useBuiltInAuth?: boolean;
12
10
  }
13
11
  declare function InsforgeMiddleware(config: InsforgeMiddlewareConfig): (request: NextRequest) => Promise<NextResponse<unknown>>;
14
- declare const withAuth: typeof InsforgeMiddleware;
15
- declare const withInsforgeAuth: typeof InsforgeMiddleware;
16
- declare function getAuthUserId(headers: Headers): string | null;
17
- declare const getAuthUser: typeof getAuthUserId;
18
- declare function getAuthToken(headers: Headers): string | null;
19
12
 
20
- export { InsforgeMiddleware, type InsforgeMiddlewareConfig, getAuthToken, getAuthUser, getAuthUserId, withAuth, withInsforgeAuth };
13
+ export { InsforgeMiddleware, type InsforgeMiddlewareConfig };
@@ -2,19 +2,12 @@ import { NextRequest, NextResponse } from 'next/server';
2
2
 
3
3
  interface InsforgeMiddlewareConfig {
4
4
  baseUrl: string;
5
- frontendUrl?: string;
6
5
  publicRoutes?: string[];
7
- afterSignInUrl?: string;
8
6
  signInUrl?: string;
9
7
  signUpUrl?: string;
10
8
  cookieName?: string;
11
9
  useBuiltInAuth?: boolean;
12
10
  }
13
11
  declare function InsforgeMiddleware(config: InsforgeMiddlewareConfig): (request: NextRequest) => Promise<NextResponse<unknown>>;
14
- declare const withAuth: typeof InsforgeMiddleware;
15
- declare const withInsforgeAuth: typeof InsforgeMiddleware;
16
- declare function getAuthUserId(headers: Headers): string | null;
17
- declare const getAuthUser: typeof getAuthUserId;
18
- declare function getAuthToken(headers: Headers): string | null;
19
12
 
20
- export { InsforgeMiddleware, type InsforgeMiddlewareConfig, getAuthToken, getAuthUser, getAuthUserId, withAuth, withInsforgeAuth };
13
+ export { InsforgeMiddleware, type InsforgeMiddlewareConfig };
@@ -21,37 +21,32 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  // src/middleware/index.ts
22
22
  var middleware_exports = {};
23
23
  __export(middleware_exports, {
24
- InsforgeMiddleware: () => InsforgeMiddleware,
25
- getAuthToken: () => getAuthToken,
26
- getAuthUser: () => getAuthUser,
27
- getAuthUserId: () => getAuthUserId,
28
- withAuth: () => withAuth,
29
- withInsforgeAuth: () => withInsforgeAuth
24
+ InsforgeMiddleware: () => InsforgeMiddleware
30
25
  });
31
26
  module.exports = __toCommonJS(middleware_exports);
32
27
 
33
28
  // src/middleware/InsforgeMiddleware.ts
34
29
  var import_server = require("next/server");
35
- var import_sdk = require("@insforge/sdk");
36
30
  function InsforgeMiddleware(config) {
37
31
  const {
38
32
  baseUrl,
39
- publicRoutes = [],
33
+ publicRoutes = ["/auth/callback", "/"],
40
34
  signInUrl = "/sign-in",
41
35
  signUpUrl = "/sign-up",
42
36
  cookieName = "insforge_token",
43
- useBuiltInAuth = true,
44
- frontendUrl
37
+ useBuiltInAuth = true
45
38
  } = config;
46
39
  return async function middleware(request) {
47
40
  const { pathname } = request.nextUrl;
41
+ if (pathname === "/auth/callback") {
42
+ return import_server.NextResponse.next();
43
+ }
48
44
  if (useBuiltInAuth && (pathname === signInUrl || pathname === signUpUrl)) {
49
45
  const callbackUrl = new URL("/auth/callback", request.url);
50
- const ossAuthUrl = new URL(`/auth${pathname}`, frontendUrl || baseUrl);
46
+ const backendAuthPath = pathname === signInUrl ? "/auth/sign-in" : "/auth/sign-up";
47
+ const ossAuthUrl = new URL(backendAuthPath, baseUrl);
51
48
  ossAuthUrl.searchParams.set("redirect", callbackUrl.toString());
52
- setTimeout(() => {
53
- return import_server.NextResponse.redirect(ossAuthUrl.toString());
54
- }, 100);
49
+ return import_server.NextResponse.redirect(ossAuthUrl.toString());
55
50
  }
56
51
  const isPublicRoute = publicRoutes.some((route) => {
57
52
  if (route.endsWith("*")) {
@@ -66,7 +61,7 @@ function InsforgeMiddleware(config) {
66
61
  if (!token) {
67
62
  if (useBuiltInAuth) {
68
63
  const callbackUrl = new URL("/auth/callback", request.url);
69
- const backendSignInUrl = new URL("/auth/signin", frontendUrl || baseUrl);
64
+ const backendSignInUrl = new URL("/auth/sign-in", baseUrl);
70
65
  backendSignInUrl.searchParams.set("redirect", callbackUrl.toString());
71
66
  return import_server.NextResponse.redirect(backendSignInUrl);
72
67
  } else {
@@ -75,65 +70,11 @@ function InsforgeMiddleware(config) {
75
70
  return import_server.NextResponse.redirect(localSignInUrl);
76
71
  }
77
72
  }
78
- try {
79
- const insforge = (0, import_sdk.createClient)({
80
- baseUrl,
81
- edgeFunctionToken: token,
82
- // Use token from cookie for this request
83
- fetch: globalThis.fetch
84
- // Ensure fetch is available in server environment
85
- });
86
- const { data: sessionData, error } = await insforge.auth.getCurrentUser();
87
- if (error || !sessionData) {
88
- console.error("[Insforge Middleware] Token validation failed:", {
89
- error: error?.message,
90
- statusCode: error?.statusCode
91
- });
92
- throw new Error("Invalid session");
93
- }
94
- const session = sessionData;
95
- const nextResponse = import_server.NextResponse.next();
96
- nextResponse.headers.set("x-user-id", session.user.id);
97
- nextResponse.headers.set("x-user-email", session.user.email);
98
- nextResponse.headers.set("x-user-token", token);
99
- if (session.profile) {
100
- const profileJson = JSON.stringify(session.profile);
101
- nextResponse.headers.set("x-user-profile", profileJson);
102
- }
103
- return nextResponse;
104
- } catch (error) {
105
- console.error("[Insforge Middleware] Token validation error:", error);
106
- const response = useBuiltInAuth ? (() => {
107
- const callbackUrl = new URL("/auth/callback", request.url);
108
- const backendSignInUrl = new URL("/auth/signin", frontendUrl || baseUrl);
109
- backendSignInUrl.searchParams.set("redirect", callbackUrl.toString());
110
- return import_server.NextResponse.redirect(backendSignInUrl);
111
- })() : (() => {
112
- const localSignInUrl = new URL(signInUrl, request.url);
113
- localSignInUrl.searchParams.set("redirect", pathname);
114
- return import_server.NextResponse.redirect(localSignInUrl);
115
- })();
116
- response.cookies.delete(cookieName);
117
- return response;
118
- }
73
+ return import_server.NextResponse.next();
119
74
  };
120
75
  }
121
- var withAuth = InsforgeMiddleware;
122
- var withInsforgeAuth = InsforgeMiddleware;
123
- function getAuthUserId(headers) {
124
- return headers.get("x-user-id");
125
- }
126
- var getAuthUser = getAuthUserId;
127
- function getAuthToken(headers) {
128
- return headers.get("x-user-token");
129
- }
130
76
  // Annotate the CommonJS export names for ESM import in node:
131
77
  0 && (module.exports = {
132
- InsforgeMiddleware,
133
- getAuthToken,
134
- getAuthUser,
135
- getAuthUserId,
136
- withAuth,
137
- withInsforgeAuth
78
+ InsforgeMiddleware
138
79
  });
139
80
  //# sourceMappingURL=middleware.js.map
@@ -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 withAuth,\r\n withInsforgeAuth,\r\n getAuthUserId, \r\n getAuthUser,\r\n getAuthToken \r\n} from './InsforgeMiddleware';\r\n\r\nexport type { InsforgeMiddlewareConfig } from './InsforgeMiddleware';\r\n\r\n","import { NextRequest, NextResponse } from 'next/server';\r\nimport { createClient } from '@insforge/sdk';\r\n\r\nexport interface InsforgeMiddlewareConfig {\r\n /**\r\n * Base URL of your Insforge backend (for API calls)\r\n * @example 'http://localhost:3001'\r\n */\r\n baseUrl: string;\r\n\r\n /**\r\n * Base URL of your frontend application (for redirects)\r\n * If not provided, will use baseUrl for redirects\r\n * @example 'http://localhost:3000'\r\n */\r\n frontendUrl?: string;\r\n\r\n /**\r\n * Routes that are public and don't require authentication\r\n * @example ['/sign-in', '/sign-up', '/']\r\n */\r\n publicRoutes?: string[];\r\n\r\n /**\r\n * URL to redirect to after sign in\r\n * @default '/dashboard'\r\n */\r\n afterSignInUrl?: string;\r\n\r\n /**\r\n * URL to redirect to when user is not authenticated\r\n * @default '/sign-in'\r\n */\r\n signInUrl?: string;\r\n\r\n /**\r\n * URL to redirect to when user is signing 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, middleware won't redirect to local sign-in pages\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 function generates a Next.js middleware that:\r\n * - Validates user authentication on each request\r\n * - Redirects unauthenticated users to sign-in page\r\n * - Allows public routes to be accessed without authentication\r\n * - Injects user information into request headers for server components\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 - Local development with separate frontend/backend URLs\r\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\r\n *\r\n * export default InsforgeMiddleware({\r\n * baseUrl: process.env.INSFORGE_BASE_URL!, // Backend API (e.g., http://localhost:3001)\r\n * frontendUrl: process.env.INSFORGE_FRONTEND_URL!, // Frontend app (e.g., http://localhost:3000)\r\n * publicRoutes: ['/auth/callback', '/'],\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 - Using custom SignIn/SignUp components\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 * frontendUrl: process.env.INSFORGE_FRONTEND_URL, // Optional: for redirects\r\n * publicRoutes: ['/sign-in', '/sign-up', '/'],\r\n * signInUrl: '/sign-in',\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\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 frontendUrl,\r\n } = config;\r\n\r\n return async function middleware(request: NextRequest) {\r\n const { pathname } = request.nextUrl;\r\n\r\n // Special handling for built-in auth: redirect /sign-in, /sign-up to OSS frontend\r\n if (useBuiltInAuth && (pathname === signInUrl || pathname === signUpUrl)) {\r\n const callbackUrl = new URL('/auth/callback', request.url);\r\n const ossAuthUrl = new URL(`/auth${pathname}`, frontendUrl || baseUrl);\r\n ossAuthUrl.searchParams.set('redirect', callbackUrl.toString());\r\n setTimeout(() => {\r\n return NextResponse.redirect(ossAuthUrl.toString());\r\n }, 100);\r\n }\r\n\r\n // Check if route is public\r\n const isPublicRoute = publicRoutes.some((route) => {\r\n if (route.endsWith('*')) {\r\n return pathname.startsWith(route.slice(0, -1));\r\n }\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 // Get token from cookie\r\n const token = request.cookies.get(cookieName)?.value;\r\n\r\n if (!token) {\r\n if (useBuiltInAuth) {\r\n // Built-in auth: redirect to backend's auth page\r\n const callbackUrl = new URL('/auth/callback', request.url);\r\n const backendSignInUrl = new URL('/auth/signin', frontendUrl || baseUrl);\r\n backendSignInUrl.searchParams.set('redirect', callbackUrl.toString());\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 try {\r\n // Use Insforge SDK to verify token and get session\r\n // SDK provides consistent error handling and returns complete user data\r\n const insforge = createClient({\r\n baseUrl,\r\n edgeFunctionToken: token, // Use token from cookie for this request\r\n fetch: globalThis.fetch, // Ensure fetch is available in server environment\r\n });\r\n\r\n const { data: sessionData, error } = await insforge.auth.getCurrentUser();\r\n\r\n if (error || !sessionData) {\r\n console.error('[Insforge Middleware] Token validation failed:', {\r\n error: error?.message,\r\n statusCode: error?.statusCode,\r\n });\r\n throw new Error('Invalid session');\r\n }\r\n\r\n const session = sessionData;\r\n\r\n // Add user info to headers for server components\r\n const nextResponse = NextResponse.next();\r\n nextResponse.headers.set('x-user-id', session.user.id);\r\n nextResponse.headers.set('x-user-email', session.user.email);\r\n nextResponse.headers.set('x-user-token', token);\r\n // Optionally add profile fields if needed\r\n if (session.profile) {\r\n const profileJson = JSON.stringify(session.profile);\r\n nextResponse.headers.set('x-user-profile', profileJson);\r\n }\r\n\r\n return nextResponse;\r\n } catch (error) {\r\n console.error('[Insforge Middleware] Token validation error:', error);\r\n\r\n // Clear invalid token first\r\n const response = useBuiltInAuth\r\n ? (() => {\r\n // Built-in auth: redirect to backend's auth page\r\n const callbackUrl = new URL('/auth/callback', request.url);\r\n const backendSignInUrl = new URL('/auth/signin', frontendUrl || baseUrl);\r\n backendSignInUrl.searchParams.set('redirect', callbackUrl.toString());\r\n return NextResponse.redirect(backendSignInUrl);\r\n })()\r\n : (() => {\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 response.cookies.delete(cookieName);\r\n return response;\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * @deprecated Use `InsforgeMiddleware` instead. This alias is kept for backward compatibility.\r\n * \r\n * Creates Next.js middleware for protecting routes with Insforge authentication.\r\n * \r\n * @see InsforgeMiddleware\r\n */\r\nexport const withAuth = InsforgeMiddleware;\r\n\r\n/**\r\n * Alternative name for `InsforgeMiddleware` with Insforge branding.\r\n * Useful when you want to be explicit about using Insforge authentication.\r\n * \r\n * @see InsforgeMiddleware\r\n */\r\nexport const withInsforgeAuth = InsforgeMiddleware;\r\n\r\n/**\r\n * Utility to get authenticated user ID from request headers in server components.\r\n * \r\n * The middleware automatically injects user information into request headers,\r\n * which can be accessed in server components using Next.js `headers()`.\r\n * \r\n * @param headers - Request headers from Next.js\r\n * @returns User ID if authenticated, null otherwise\r\n *\r\n * @example\r\n * ```ts\r\n * import { headers } from 'next/headers';\r\n * import { getAuthUserId } from '@insforge/nextjs/middleware';\r\n *\r\n * export default async function DashboardPage() {\r\n * const userId = getAuthUserId(headers());\r\n * \r\n * if (!userId) {\r\n * return <div>Not authenticated</div>;\r\n * }\r\n * \r\n * return <div>User ID: {userId}</div>;\r\n * }\r\n * ```\r\n */\r\nexport function getAuthUserId(headers: Headers): string | null {\r\n return headers.get('x-user-id');\r\n}\r\n\r\n/**\r\n * @deprecated Use `getAuthUserId` instead. This alias is kept for backward compatibility.\r\n * @see getAuthUserId\r\n */\r\nexport const getAuthUser = getAuthUserId;\r\n\r\n/**\r\n * Utility to get auth token from request headers in server components.\r\n * \r\n * The middleware automatically injects the authentication token into request headers,\r\n * which can be used to make authenticated API calls from server components.\r\n * \r\n * @param headers - Request headers from Next.js\r\n * @returns Auth token if authenticated, null otherwise\r\n * \r\n * @example\r\n * ```ts\r\n * import { headers } from 'next/headers';\r\n * import { getAuthToken } from '@insforge/nextjs/middleware';\r\n *\r\n * export default async function ProfilePage() {\r\n * const token = getAuthToken(headers());\r\n * \r\n * if (!token) {\r\n * return <div>Not authenticated</div>;\r\n * }\r\n * \r\n * // Use token for API calls\r\n * const response = await fetch('https://api.example.com/profile', {\r\n * headers: { Authorization: `Bearer ${token}` }\r\n * });\r\n * \r\n * return <div>Profile data</div>;\r\n * }\r\n * ```\r\n */\r\nexport function getAuthToken(headers: Headers): string | null {\r\n return headers.get('x-user-token');\r\n}\r\n"],"mappings":"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","names":[]}
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 * Note: `/auth/callback` is automatically treated as public\r\n * @default ['/auth/callback', '/']\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 * - 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 * - Always allowing `/auth/callback` through (for token extraction)\r\n * - Mapping local auth routes to backend's fixed paths when using built-in auth\r\n * \r\n * **Important Notes:**\r\n * - This middleware only checks if a token exists, it doesn't validate it\r\n * - `/auth/callback` is automatically treated as public (handles query param tokens)\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 with separate frontend/backend URLs\r\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\r\n *\r\n * export default InsforgeMiddleware({\r\n * baseUrl: process.env.INSFORGE_BASE_URL!, // Backend: http://localhost:3001\r\n * frontendUrl: process.env.INSFORGE_FRONTEND_URL!, // Frontend: http://localhost:3000\r\n * publicRoutes: ['/', '/about'], // /auth/callback is auto-included\r\n * useBuiltInAuth: true, // Use backend's auth pages\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', // Custom local path\r\n * signUpUrl: '/register', // Custom local path\r\n * useBuiltInAuth: false, // Use your own SignIn/SignUp components\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 * // Local '/login' and '/register' routes redirect to backend's '/auth/sign-in' and '/auth/sign-up'\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', // Local path (redirects to backend /auth/sign-in)\r\n * signUpUrl: '/register', // Local path (redirects to backend /auth/sign-up)\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 = [\"/auth/callback\", \"/\"],\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 } = request.nextUrl;\r\n\r\n // STEP 1: Always allow /auth/callback through\r\n // This route must be public because it receives the token as a query parameter\r\n // and the InsforgeProvider processes it on the client side\r\n if (pathname === '/auth/callback') {\r\n return NextResponse.next();\r\n }\r\n\r\n // STEP 2: Handle built-in auth redirects\r\n // Map local sign-in/sign-up routes to backend's fixed auth pages\r\n // Example: local '/login' → backend '/auth/sign-in'\r\n if (useBuiltInAuth && (pathname === signInUrl || pathname === signUpUrl)) {\r\n const callbackUrl = new URL('/auth/callback', request.url);\r\n // Backend auth routes are FIXED: /auth/sign-in and /auth/sign-up (with hyphen)\r\n const backendAuthPath = pathname === signInUrl ? '/auth/sign-in' : '/auth/sign-up';\r\n const ossAuthUrl = new URL(backendAuthPath, baseUrl);\r\n ossAuthUrl.searchParams.set('redirect', callbackUrl.toString());\r\n return NextResponse.redirect(ossAuthUrl.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 // Note: We only check if token exists, we don't validate it here\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 const callbackUrl = new URL('/auth/callback', request.url);\r\n const backendSignInUrl = new URL('/auth/sign-in', baseUrl);\r\n backendSignInUrl.searchParams.set('redirect', callbackUrl.toString());\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, allow request to continue\r\n return NextResponse.next();\r\n };\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAA0C;AAkHnC,SAAS,mBAAmB,QAAkC;AACnE,QAAM;AAAA,IACJ;AAAA,IACA,eAAe,CAAC,kBAAkB,GAAG;AAAA,IACrC,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,iBAAiB;AAAA,EACnB,IAAI;AAEJ,SAAO,eAAe,WAAW,SAAsB;AACrD,UAAM,EAAE,SAAS,IAAI,QAAQ;AAK7B,QAAI,aAAa,kBAAkB;AACjC,aAAO,2BAAa,KAAK;AAAA,IAC3B;AAKA,QAAI,mBAAmB,aAAa,aAAa,aAAa,YAAY;AACxE,YAAM,cAAc,IAAI,IAAI,kBAAkB,QAAQ,GAAG;AAEzD,YAAM,kBAAkB,aAAa,YAAY,kBAAkB;AACnE,YAAM,aAAa,IAAI,IAAI,iBAAiB,OAAO;AACnD,iBAAW,aAAa,IAAI,YAAY,YAAY,SAAS,CAAC;AAC9D,aAAO,2BAAa,SAAS,WAAW,SAAS,CAAC;AAAA,IACpD;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;AAIA,UAAM,QAAQ,QAAQ,QAAQ,IAAI,UAAU,GAAG;AAE/C,QAAI,CAAC,OAAO;AAEV,UAAI,gBAAgB;AAElB,cAAM,cAAc,IAAI,IAAI,kBAAkB,QAAQ,GAAG;AACzD,cAAM,mBAAmB,IAAI,IAAI,iBAAiB,OAAO;AACzD,yBAAiB,aAAa,IAAI,YAAY,YAAY,SAAS,CAAC;AACpE,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":[]}
@@ -2,26 +2,26 @@
2
2
 
3
3
  // src/middleware/InsforgeMiddleware.ts
4
4
  import { NextResponse } from "next/server";
5
- import { createClient } from "@insforge/sdk";
6
5
  function InsforgeMiddleware(config) {
7
6
  const {
8
7
  baseUrl,
9
- publicRoutes = [],
8
+ publicRoutes = ["/auth/callback", "/"],
10
9
  signInUrl = "/sign-in",
11
10
  signUpUrl = "/sign-up",
12
11
  cookieName = "insforge_token",
13
- useBuiltInAuth = true,
14
- frontendUrl
12
+ useBuiltInAuth = true
15
13
  } = config;
16
14
  return async function middleware(request) {
17
15
  const { pathname } = request.nextUrl;
16
+ if (pathname === "/auth/callback") {
17
+ return NextResponse.next();
18
+ }
18
19
  if (useBuiltInAuth && (pathname === signInUrl || pathname === signUpUrl)) {
19
20
  const callbackUrl = new URL("/auth/callback", request.url);
20
- const ossAuthUrl = new URL(`/auth${pathname}`, frontendUrl || baseUrl);
21
+ const backendAuthPath = pathname === signInUrl ? "/auth/sign-in" : "/auth/sign-up";
22
+ const ossAuthUrl = new URL(backendAuthPath, baseUrl);
21
23
  ossAuthUrl.searchParams.set("redirect", callbackUrl.toString());
22
- setTimeout(() => {
23
- return NextResponse.redirect(ossAuthUrl.toString());
24
- }, 100);
24
+ return NextResponse.redirect(ossAuthUrl.toString());
25
25
  }
26
26
  const isPublicRoute = publicRoutes.some((route) => {
27
27
  if (route.endsWith("*")) {
@@ -36,7 +36,7 @@ function InsforgeMiddleware(config) {
36
36
  if (!token) {
37
37
  if (useBuiltInAuth) {
38
38
  const callbackUrl = new URL("/auth/callback", request.url);
39
- const backendSignInUrl = new URL("/auth/signin", frontendUrl || baseUrl);
39
+ const backendSignInUrl = new URL("/auth/sign-in", baseUrl);
40
40
  backendSignInUrl.searchParams.set("redirect", callbackUrl.toString());
41
41
  return NextResponse.redirect(backendSignInUrl);
42
42
  } else {
@@ -45,64 +45,10 @@ function InsforgeMiddleware(config) {
45
45
  return NextResponse.redirect(localSignInUrl);
46
46
  }
47
47
  }
48
- try {
49
- const insforge = createClient({
50
- baseUrl,
51
- edgeFunctionToken: token,
52
- // Use token from cookie for this request
53
- fetch: globalThis.fetch
54
- // Ensure fetch is available in server environment
55
- });
56
- const { data: sessionData, error } = await insforge.auth.getCurrentUser();
57
- if (error || !sessionData) {
58
- console.error("[Insforge Middleware] Token validation failed:", {
59
- error: error?.message,
60
- statusCode: error?.statusCode
61
- });
62
- throw new Error("Invalid session");
63
- }
64
- const session = sessionData;
65
- const nextResponse = NextResponse.next();
66
- nextResponse.headers.set("x-user-id", session.user.id);
67
- nextResponse.headers.set("x-user-email", session.user.email);
68
- nextResponse.headers.set("x-user-token", token);
69
- if (session.profile) {
70
- const profileJson = JSON.stringify(session.profile);
71
- nextResponse.headers.set("x-user-profile", profileJson);
72
- }
73
- return nextResponse;
74
- } catch (error) {
75
- console.error("[Insforge Middleware] Token validation error:", error);
76
- const response = useBuiltInAuth ? (() => {
77
- const callbackUrl = new URL("/auth/callback", request.url);
78
- const backendSignInUrl = new URL("/auth/signin", frontendUrl || baseUrl);
79
- backendSignInUrl.searchParams.set("redirect", callbackUrl.toString());
80
- return NextResponse.redirect(backendSignInUrl);
81
- })() : (() => {
82
- const localSignInUrl = new URL(signInUrl, request.url);
83
- localSignInUrl.searchParams.set("redirect", pathname);
84
- return NextResponse.redirect(localSignInUrl);
85
- })();
86
- response.cookies.delete(cookieName);
87
- return response;
88
- }
48
+ return NextResponse.next();
89
49
  };
90
50
  }
91
- var withAuth = InsforgeMiddleware;
92
- var withInsforgeAuth = InsforgeMiddleware;
93
- function getAuthUserId(headers) {
94
- return headers.get("x-user-id");
95
- }
96
- var getAuthUser = getAuthUserId;
97
- function getAuthToken(headers) {
98
- return headers.get("x-user-token");
99
- }
100
51
  export {
101
- InsforgeMiddleware,
102
- getAuthToken,
103
- getAuthUser,
104
- getAuthUserId,
105
- withAuth,
106
- withInsforgeAuth
52
+ InsforgeMiddleware
107
53
  };
108
54
  //# sourceMappingURL=middleware.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/middleware/InsforgeMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\r\nimport { createClient } from '@insforge/sdk';\r\n\r\nexport interface InsforgeMiddlewareConfig {\r\n /**\r\n * Base URL of your Insforge backend (for API calls)\r\n * @example 'http://localhost:3001'\r\n */\r\n baseUrl: string;\r\n\r\n /**\r\n * Base URL of your frontend application (for redirects)\r\n * If not provided, will use baseUrl for redirects\r\n * @example 'http://localhost:3000'\r\n */\r\n frontendUrl?: string;\r\n\r\n /**\r\n * Routes that are public and don't require authentication\r\n * @example ['/sign-in', '/sign-up', '/']\r\n */\r\n publicRoutes?: string[];\r\n\r\n /**\r\n * URL to redirect to after sign in\r\n * @default '/dashboard'\r\n */\r\n afterSignInUrl?: string;\r\n\r\n /**\r\n * URL to redirect to when user is not authenticated\r\n * @default '/sign-in'\r\n */\r\n signInUrl?: string;\r\n\r\n /**\r\n * URL to redirect to when user is signing 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, middleware won't redirect to local sign-in pages\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 function generates a Next.js middleware that:\r\n * - Validates user authentication on each request\r\n * - Redirects unauthenticated users to sign-in page\r\n * - Allows public routes to be accessed without authentication\r\n * - Injects user information into request headers for server components\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 - Local development with separate frontend/backend URLs\r\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\r\n *\r\n * export default InsforgeMiddleware({\r\n * baseUrl: process.env.INSFORGE_BASE_URL!, // Backend API (e.g., http://localhost:3001)\r\n * frontendUrl: process.env.INSFORGE_FRONTEND_URL!, // Frontend app (e.g., http://localhost:3000)\r\n * publicRoutes: ['/auth/callback', '/'],\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 - Using custom SignIn/SignUp components\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 * frontendUrl: process.env.INSFORGE_FRONTEND_URL, // Optional: for redirects\r\n * publicRoutes: ['/sign-in', '/sign-up', '/'],\r\n * signInUrl: '/sign-in',\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\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 frontendUrl,\r\n } = config;\r\n\r\n return async function middleware(request: NextRequest) {\r\n const { pathname } = request.nextUrl;\r\n\r\n // Special handling for built-in auth: redirect /sign-in, /sign-up to OSS frontend\r\n if (useBuiltInAuth && (pathname === signInUrl || pathname === signUpUrl)) {\r\n const callbackUrl = new URL('/auth/callback', request.url);\r\n const ossAuthUrl = new URL(`/auth${pathname}`, frontendUrl || baseUrl);\r\n ossAuthUrl.searchParams.set('redirect', callbackUrl.toString());\r\n setTimeout(() => {\r\n return NextResponse.redirect(ossAuthUrl.toString());\r\n }, 100);\r\n }\r\n\r\n // Check if route is public\r\n const isPublicRoute = publicRoutes.some((route) => {\r\n if (route.endsWith('*')) {\r\n return pathname.startsWith(route.slice(0, -1));\r\n }\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 // Get token from cookie\r\n const token = request.cookies.get(cookieName)?.value;\r\n\r\n if (!token) {\r\n if (useBuiltInAuth) {\r\n // Built-in auth: redirect to backend's auth page\r\n const callbackUrl = new URL('/auth/callback', request.url);\r\n const backendSignInUrl = new URL('/auth/signin', frontendUrl || baseUrl);\r\n backendSignInUrl.searchParams.set('redirect', callbackUrl.toString());\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 try {\r\n // Use Insforge SDK to verify token and get session\r\n // SDK provides consistent error handling and returns complete user data\r\n const insforge = createClient({\r\n baseUrl,\r\n edgeFunctionToken: token, // Use token from cookie for this request\r\n fetch: globalThis.fetch, // Ensure fetch is available in server environment\r\n });\r\n\r\n const { data: sessionData, error } = await insforge.auth.getCurrentUser();\r\n\r\n if (error || !sessionData) {\r\n console.error('[Insforge Middleware] Token validation failed:', {\r\n error: error?.message,\r\n statusCode: error?.statusCode,\r\n });\r\n throw new Error('Invalid session');\r\n }\r\n\r\n const session = sessionData;\r\n\r\n // Add user info to headers for server components\r\n const nextResponse = NextResponse.next();\r\n nextResponse.headers.set('x-user-id', session.user.id);\r\n nextResponse.headers.set('x-user-email', session.user.email);\r\n nextResponse.headers.set('x-user-token', token);\r\n // Optionally add profile fields if needed\r\n if (session.profile) {\r\n const profileJson = JSON.stringify(session.profile);\r\n nextResponse.headers.set('x-user-profile', profileJson);\r\n }\r\n\r\n return nextResponse;\r\n } catch (error) {\r\n console.error('[Insforge Middleware] Token validation error:', error);\r\n\r\n // Clear invalid token first\r\n const response = useBuiltInAuth\r\n ? (() => {\r\n // Built-in auth: redirect to backend's auth page\r\n const callbackUrl = new URL('/auth/callback', request.url);\r\n const backendSignInUrl = new URL('/auth/signin', frontendUrl || baseUrl);\r\n backendSignInUrl.searchParams.set('redirect', callbackUrl.toString());\r\n return NextResponse.redirect(backendSignInUrl);\r\n })()\r\n : (() => {\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 response.cookies.delete(cookieName);\r\n return response;\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * @deprecated Use `InsforgeMiddleware` instead. This alias is kept for backward compatibility.\r\n * \r\n * Creates Next.js middleware for protecting routes with Insforge authentication.\r\n * \r\n * @see InsforgeMiddleware\r\n */\r\nexport const withAuth = InsforgeMiddleware;\r\n\r\n/**\r\n * Alternative name for `InsforgeMiddleware` with Insforge branding.\r\n * Useful when you want to be explicit about using Insforge authentication.\r\n * \r\n * @see InsforgeMiddleware\r\n */\r\nexport const withInsforgeAuth = InsforgeMiddleware;\r\n\r\n/**\r\n * Utility to get authenticated user ID from request headers in server components.\r\n * \r\n * The middleware automatically injects user information into request headers,\r\n * which can be accessed in server components using Next.js `headers()`.\r\n * \r\n * @param headers - Request headers from Next.js\r\n * @returns User ID if authenticated, null otherwise\r\n *\r\n * @example\r\n * ```ts\r\n * import { headers } from 'next/headers';\r\n * import { getAuthUserId } from '@insforge/nextjs/middleware';\r\n *\r\n * export default async function DashboardPage() {\r\n * const userId = getAuthUserId(headers());\r\n * \r\n * if (!userId) {\r\n * return <div>Not authenticated</div>;\r\n * }\r\n * \r\n * return <div>User ID: {userId}</div>;\r\n * }\r\n * ```\r\n */\r\nexport function getAuthUserId(headers: Headers): string | null {\r\n return headers.get('x-user-id');\r\n}\r\n\r\n/**\r\n * @deprecated Use `getAuthUserId` instead. This alias is kept for backward compatibility.\r\n * @see getAuthUserId\r\n */\r\nexport const getAuthUser = getAuthUserId;\r\n\r\n/**\r\n * Utility to get auth token from request headers in server components.\r\n * \r\n * The middleware automatically injects the authentication token into request headers,\r\n * which can be used to make authenticated API calls from server components.\r\n * \r\n * @param headers - Request headers from Next.js\r\n * @returns Auth token if authenticated, null otherwise\r\n * \r\n * @example\r\n * ```ts\r\n * import { headers } from 'next/headers';\r\n * import { getAuthToken } from '@insforge/nextjs/middleware';\r\n *\r\n * export default async function ProfilePage() {\r\n * const token = getAuthToken(headers());\r\n * \r\n * if (!token) {\r\n * return <div>Not authenticated</div>;\r\n * }\r\n * \r\n * // Use token for API calls\r\n * const response = await fetch('https://api.example.com/profile', {\r\n * headers: { Authorization: `Bearer ${token}` }\r\n * });\r\n * \r\n * return <div>Profile data</div>;\r\n * }\r\n * ```\r\n */\r\nexport function getAuthToken(headers: Headers): string | null {\r\n return headers.get('x-user-token');\r\n}\r\n"],"mappings":";;;AAAA,SAAsB,oBAAoB;AAC1C,SAAS,oBAAoB;AAoGtB,SAAS,mBAAmB,QAAkC;AACnE,QAAM;AAAA,IACJ;AAAA,IACA,eAAe,CAAC;AAAA,IAChB,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB;AAAA,EACF,IAAI;AAEJ,SAAO,eAAe,WAAW,SAAsB;AACrD,UAAM,EAAE,SAAS,IAAI,QAAQ;AAG7B,QAAI,mBAAmB,aAAa,aAAa,aAAa,YAAY;AACxE,YAAM,cAAc,IAAI,IAAI,kBAAkB,QAAQ,GAAG;AACzD,YAAM,aAAa,IAAI,IAAI,QAAQ,QAAQ,IAAI,eAAe,OAAO;AACrE,iBAAW,aAAa,IAAI,YAAY,YAAY,SAAS,CAAC;AAC9D,iBAAW,MAAM;AACf,eAAO,aAAa,SAAS,WAAW,SAAS,CAAC;AAAA,MACpD,GAAG,GAAG;AAAA,IACR;AAGA,UAAM,gBAAgB,aAAa,KAAK,CAAC,UAAU;AACjD,UAAI,MAAM,SAAS,GAAG,GAAG;AACvB,eAAO,SAAS,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,MAC/C;AACA,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;AACV,UAAI,gBAAgB;AAElB,cAAM,cAAc,IAAI,IAAI,kBAAkB,QAAQ,GAAG;AACzD,cAAM,mBAAmB,IAAI,IAAI,gBAAgB,eAAe,OAAO;AACvE,yBAAiB,aAAa,IAAI,YAAY,YAAY,SAAS,CAAC;AACpE,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;AAEA,QAAI;AAGF,YAAM,WAAW,aAAa;AAAA,QAC5B;AAAA,QACA,mBAAmB;AAAA;AAAA,QACnB,OAAO,WAAW;AAAA;AAAA,MACpB,CAAC;AAED,YAAM,EAAE,MAAM,aAAa,MAAM,IAAI,MAAM,SAAS,KAAK,eAAe;AAExE,UAAI,SAAS,CAAC,aAAa;AACzB,gBAAQ,MAAM,kDAAkD;AAAA,UAC9D,OAAO,OAAO;AAAA,UACd,YAAY,OAAO;AAAA,QACrB,CAAC;AACD,cAAM,IAAI,MAAM,iBAAiB;AAAA,MACnC;AAEA,YAAM,UAAU;AAGhB,YAAM,eAAe,aAAa,KAAK;AACvC,mBAAa,QAAQ,IAAI,aAAa,QAAQ,KAAK,EAAE;AACrD,mBAAa,QAAQ,IAAI,gBAAgB,QAAQ,KAAK,KAAK;AAC3D,mBAAa,QAAQ,IAAI,gBAAgB,KAAK;AAE9C,UAAI,QAAQ,SAAS;AACnB,cAAM,cAAc,KAAK,UAAU,QAAQ,OAAO;AAClD,qBAAa,QAAQ,IAAI,kBAAkB,WAAW;AAAA,MACxD;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,iDAAiD,KAAK;AAGpE,YAAM,WAAW,kBACZ,MAAM;AAEP,cAAM,cAAc,IAAI,IAAI,kBAAkB,QAAQ,GAAG;AACzD,cAAM,mBAAmB,IAAI,IAAI,gBAAgB,eAAe,OAAO;AACvE,yBAAiB,aAAa,IAAI,YAAY,YAAY,SAAS,CAAC;AACpE,eAAO,aAAa,SAAS,gBAAgB;AAAA,MAC/C,GAAG,KACA,MAAM;AAEP,cAAM,iBAAiB,IAAI,IAAI,WAAW,QAAQ,GAAG;AACrD,uBAAe,aAAa,IAAI,YAAY,QAAQ;AACpD,eAAO,aAAa,SAAS,cAAc;AAAA,MAC7C,GAAG;AAEL,eAAS,QAAQ,OAAO,UAAU;AAClC,aAAO;AAAA,IACT;AAAA,EACF;AACF;AASO,IAAM,WAAW;AAQjB,IAAM,mBAAmB;AA2BzB,SAAS,cAAc,SAAiC;AAC7D,SAAO,QAAQ,IAAI,WAAW;AAChC;AAMO,IAAM,cAAc;AAgCpB,SAAS,aAAa,SAAiC;AAC5D,SAAO,QAAQ,IAAI,cAAc;AACnC;","names":[]}
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 * Note: `/auth/callback` is automatically treated as public\r\n * @default ['/auth/callback', '/']\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 * - 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 * - Always allowing `/auth/callback` through (for token extraction)\r\n * - Mapping local auth routes to backend's fixed paths when using built-in auth\r\n * \r\n * **Important Notes:**\r\n * - This middleware only checks if a token exists, it doesn't validate it\r\n * - `/auth/callback` is automatically treated as public (handles query param tokens)\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 with separate frontend/backend URLs\r\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\r\n *\r\n * export default InsforgeMiddleware({\r\n * baseUrl: process.env.INSFORGE_BASE_URL!, // Backend: http://localhost:3001\r\n * frontendUrl: process.env.INSFORGE_FRONTEND_URL!, // Frontend: http://localhost:3000\r\n * publicRoutes: ['/', '/about'], // /auth/callback is auto-included\r\n * useBuiltInAuth: true, // Use backend's auth pages\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', // Custom local path\r\n * signUpUrl: '/register', // Custom local path\r\n * useBuiltInAuth: false, // Use your own SignIn/SignUp components\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 * // Local '/login' and '/register' routes redirect to backend's '/auth/sign-in' and '/auth/sign-up'\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', // Local path (redirects to backend /auth/sign-in)\r\n * signUpUrl: '/register', // Local path (redirects to backend /auth/sign-up)\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 = [\"/auth/callback\", \"/\"],\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 } = request.nextUrl;\r\n\r\n // STEP 1: Always allow /auth/callback through\r\n // This route must be public because it receives the token as a query parameter\r\n // and the InsforgeProvider processes it on the client side\r\n if (pathname === '/auth/callback') {\r\n return NextResponse.next();\r\n }\r\n\r\n // STEP 2: Handle built-in auth redirects\r\n // Map local sign-in/sign-up routes to backend's fixed auth pages\r\n // Example: local '/login' → backend '/auth/sign-in'\r\n if (useBuiltInAuth && (pathname === signInUrl || pathname === signUpUrl)) {\r\n const callbackUrl = new URL('/auth/callback', request.url);\r\n // Backend auth routes are FIXED: /auth/sign-in and /auth/sign-up (with hyphen)\r\n const backendAuthPath = pathname === signInUrl ? '/auth/sign-in' : '/auth/sign-up';\r\n const ossAuthUrl = new URL(backendAuthPath, baseUrl);\r\n ossAuthUrl.searchParams.set('redirect', callbackUrl.toString());\r\n return NextResponse.redirect(ossAuthUrl.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 // Note: We only check if token exists, we don't validate it here\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 const callbackUrl = new URL('/auth/callback', request.url);\r\n const backendSignInUrl = new URL('/auth/sign-in', baseUrl);\r\n backendSignInUrl.searchParams.set('redirect', callbackUrl.toString());\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, allow request to continue\r\n return NextResponse.next();\r\n };\r\n}"],"mappings":";;;AAAA,SAAsB,oBAAoB;AAkHnC,SAAS,mBAAmB,QAAkC;AACnE,QAAM;AAAA,IACJ;AAAA,IACA,eAAe,CAAC,kBAAkB,GAAG;AAAA,IACrC,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,iBAAiB;AAAA,EACnB,IAAI;AAEJ,SAAO,eAAe,WAAW,SAAsB;AACrD,UAAM,EAAE,SAAS,IAAI,QAAQ;AAK7B,QAAI,aAAa,kBAAkB;AACjC,aAAO,aAAa,KAAK;AAAA,IAC3B;AAKA,QAAI,mBAAmB,aAAa,aAAa,aAAa,YAAY;AACxE,YAAM,cAAc,IAAI,IAAI,kBAAkB,QAAQ,GAAG;AAEzD,YAAM,kBAAkB,aAAa,YAAY,kBAAkB;AACnE,YAAM,aAAa,IAAI,IAAI,iBAAiB,OAAO;AACnD,iBAAW,aAAa,IAAI,YAAY,YAAY,SAAS,CAAC;AAC9D,aAAO,aAAa,SAAS,WAAW,SAAS,CAAC;AAAA,IACpD;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;AAIA,UAAM,QAAQ,QAAQ,QAAQ,IAAI,UAAU,GAAG;AAE/C,QAAI,CAAC,OAAO;AAEV,UAAI,gBAAgB;AAElB,cAAM,cAAc,IAAI,IAAI,kBAAkB,QAAQ,GAAG;AACzD,cAAM,mBAAmB,IAAI,IAAI,iBAAiB,OAAO;AACzD,yBAAiB,aAAa,IAAI,YAAY,YAAY,SAAS,CAAC;AACpE,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.6",
3
+ "version": "0.8.8",
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.3.1",
53
+ "@insforge/react": "^0.3.2",
54
54
  "@insforge/sdk": "0.0.58-dev.13",
55
55
  "@insforge/shared-schemas": "^1.1.17",
56
56
  "clsx": "^2.1.1",