@insforge/nextjs 1.0.2-dev.2 → 1.0.2-dev.3
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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
|
-
import { COOKIE_NAMES } from "../lib/cookies";
|
|
2
|
+
import { COOKIE_NAMES, getBaseCookieOptions, serializeUserCookie } from "../lib/cookies";
|
|
3
3
|
const InsforgeMiddleware = (config) => {
|
|
4
4
|
const {
|
|
5
5
|
baseUrl,
|
|
@@ -11,7 +11,22 @@ const InsforgeMiddleware = (config) => {
|
|
|
11
11
|
useBuiltInAuth = true
|
|
12
12
|
} = config;
|
|
13
13
|
return function middleware(request) {
|
|
14
|
-
const { pathname } = request.nextUrl;
|
|
14
|
+
const { pathname, searchParams } = request.nextUrl;
|
|
15
|
+
const accessToken = searchParams.get("access_token");
|
|
16
|
+
const userId = searchParams.get("user_id");
|
|
17
|
+
const email = searchParams.get("email");
|
|
18
|
+
const name = searchParams.get("name");
|
|
19
|
+
if (accessToken && userId && email) {
|
|
20
|
+
const response = NextResponse.next();
|
|
21
|
+
const cookieOptions = getBaseCookieOptions();
|
|
22
|
+
response.cookies.set(COOKIE_NAMES.SESSION, accessToken, cookieOptions);
|
|
23
|
+
response.cookies.set(
|
|
24
|
+
COOKIE_NAMES.USER,
|
|
25
|
+
serializeUserCookie({ id: userId, email, name: name || void 0 }),
|
|
26
|
+
cookieOptions
|
|
27
|
+
);
|
|
28
|
+
return response;
|
|
29
|
+
}
|
|
15
30
|
if (useBuiltInAuth) {
|
|
16
31
|
const authRouteMapping = {
|
|
17
32
|
[signInUrl]: "/auth/sign-in",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/middleware/InsforgeMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport { COOKIE_NAMES } from '../lib/cookies';\n\nexport interface InsforgeMiddlewareConfig {\n /**\n * Base URL of your Insforge backend\n * @example 'https://your-backend.com' or 'http://localhost:3001'\n */\n baseUrl: string;\n\n /**\n * Routes that are public and don't require authentication\n * @default ['/']\n * @example ['/sign-in', '/sign-up', '/', '/about']\n */\n publicRoutes?: string[];\n\n /**\n * Local route path for sign-in (can be customized to any path like '/login')\n * When using built-in auth, this will redirect to backend's `/auth/sign-in`\n * @default '/sign-in'\n */\n signInUrl?: string;\n\n /**\n * Local route path for sign-up (can be customized to any path like '/register')\n * When using built-in auth, this will redirect to backend's `/auth/sign-up`\n * @default '/sign-up'\n */\n signUpUrl?: string;\n\n /**\n * Local route path for forgot password\n * When using built-in auth, this will redirect to backend's `/auth/forgot-password`\n * @default '/forgot-password'\n */\n forgotPasswordUrl?: string;\n\n /**\n * URL to redirect to after successful authentication\n * When user completes sign-in/sign-up, they will be redirected to this URL with token in URL\n * @default '/'\n */\n afterSignInUrl?: string;\n\n /**\n * Whether to use built-in authentication pages hosted on the backend\n * - When true: redirects to backend's `/auth/sign-in` and `/auth/sign-up` pages\n * - When false: redirects to local sign-in/sign-up pages (you provide your own components)\n * @default true\n */\n useBuiltInAuth?: boolean;\n}\n\n/**\n * Creates Next.js middleware for protecting routes with Insforge authentication.\n *\n * This middleware provides lightweight route protection by:\n * - Detecting and storing auth tokens from URL parameters (after backend redirect)\n * - Checking for auth token presence in cookies\n * - Redirecting unauthenticated users to sign-in page\n * - Allowing public routes to be accessed without authentication\n * - Mapping local auth routes to backend's fixed paths when using built-in auth\n *\n * **How Authentication Flow Works:**\n * 1. User visits protected route → Middleware checks for token\n * 2. No token → Redirects to sign-in (backend or local)\n * 3. User accesses auth page (e.g., /sign-in) → Redirects to backend with afterSignInUrl as redirect target\n * 4. After sign-in → Backend redirects to `yourapp.com/afterSignInUrl?access_token=xxx&user_id=xxx...`\n * 5. Middleware detects `access_token` in URL → Stores in HTTP-only cookie → Cleans URL → Allows access\n * 6. SDK also detects token from URL → Stores in localStorage → Updates auth state\n *\n * **Important Notes:**\n * - This middleware only checks if a token exists, it doesn't validate it\n * - Tokens from URL are automatically extracted and stored in cookies\n * - When `useBuiltInAuth: true`, local routes map to backend's fixed auth paths\n * - You can customize local route paths (e.g., `/login`) while backend paths remain fixed\n * - After successful auth, users are redirected to `afterSignInUrl` (default: `/`), not back to the auth page\n *\n * @param config - Middleware configuration\n * @returns Next.js middleware function\n *\n * @example\n * ```ts\n * // middleware.ts - Using built-in auth\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\n *\n * export default InsforgeMiddleware({\n * baseUrl: process.env.INSFORGE_BASE_URL!,\n * publicRoutes: ['/', '/about'],\n * afterSignInUrl: '/', // Redirect here after successful auth\n * useBuiltInAuth: true,\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\n * };\n * ```\n *\n * @example\n * ```ts\n * // middleware.ts - Custom local auth pages with custom paths\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\n *\n * export default InsforgeMiddleware({\n * baseUrl: process.env.INSFORGE_BASE_URL!,\n * publicRoutes: ['/login', '/register', '/', '/about'],\n * signInUrl: '/login',\n * signUpUrl: '/register',\n * afterSignInUrl: '/dashboard',\n * useBuiltInAuth: false,\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\n * };\n * ```\n *\n * @example\n * ```ts\n * // middleware.ts - Built-in auth with custom auth route paths\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\n *\n * export default InsforgeMiddleware({\n * baseUrl: 'https://your-backend.com',\n * signInUrl: '/login',\n * signUpUrl: '/register',\n * forgotPasswordUrl: '/forgot',\n * afterSignInUrl: '/dashboard',\n * useBuiltInAuth: true,\n * });\n * ```\n */\nexport const InsforgeMiddleware = (config: InsforgeMiddlewareConfig) => {\n const {\n baseUrl,\n publicRoutes = ['/'],\n signInUrl = '/sign-in',\n signUpUrl = '/sign-up',\n forgotPasswordUrl = '/forgot-password',\n afterSignInUrl = '/',\n useBuiltInAuth = true,\n } = config;\n\n return function middleware(request: NextRequest) {\n const { pathname } = request.nextUrl;\n\n // STEP 1: Handle built-in auth redirects for authentication pages\n // Map local auth routes to backend's fixed auth pages\n if (useBuiltInAuth) {\n const authRouteMapping: Record<string, string> = {\n [signInUrl]: '/auth/sign-in',\n [signUpUrl]: '/auth/sign-up',\n [forgotPasswordUrl]: '/auth/forgot-password',\n };\n\n const backendAuthPath = authRouteMapping[pathname];\n if (backendAuthPath) {\n // Redirect to afterSignInUrl after successful authentication\n const redirectUrl = new URL(afterSignInUrl, request.url).toString();\n const backendAuthUrl = new URL(backendAuthPath, baseUrl);\n backendAuthUrl.searchParams.set('redirect', redirectUrl);\n return NextResponse.redirect(backendAuthUrl.toString());\n }\n }\n\n // STEP
|
|
1
|
+
{"version":3,"sources":["../../../src/middleware/InsforgeMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport { COOKIE_NAMES, getBaseCookieOptions, serializeUserCookie } from '../lib/cookies';\n\nexport interface InsforgeMiddlewareConfig {\n /**\n * Base URL of your Insforge backend\n * @example 'https://your-backend.com' or 'http://localhost:3001'\n */\n baseUrl: string;\n\n /**\n * Routes that are public and don't require authentication\n * @default ['/']\n * @example ['/sign-in', '/sign-up', '/', '/about']\n */\n publicRoutes?: string[];\n\n /**\n * Local route path for sign-in (can be customized to any path like '/login')\n * When using built-in auth, this will redirect to backend's `/auth/sign-in`\n * @default '/sign-in'\n */\n signInUrl?: string;\n\n /**\n * Local route path for sign-up (can be customized to any path like '/register')\n * When using built-in auth, this will redirect to backend's `/auth/sign-up`\n * @default '/sign-up'\n */\n signUpUrl?: string;\n\n /**\n * Local route path for forgot password\n * When using built-in auth, this will redirect to backend's `/auth/forgot-password`\n * @default '/forgot-password'\n */\n forgotPasswordUrl?: string;\n\n /**\n * URL to redirect to after successful authentication\n * When user completes sign-in/sign-up, they will be redirected to this URL with token in URL\n * @default '/'\n */\n afterSignInUrl?: string;\n\n /**\n * Whether to use built-in authentication pages hosted on the backend\n * - When true: redirects to backend's `/auth/sign-in` and `/auth/sign-up` pages\n * - When false: redirects to local sign-in/sign-up pages (you provide your own components)\n * @default true\n */\n useBuiltInAuth?: boolean;\n}\n\n/**\n * Creates Next.js middleware for protecting routes with Insforge authentication.\n *\n * This middleware provides lightweight route protection by:\n * - Detecting and storing auth tokens from URL parameters (after backend redirect)\n * - Checking for auth token presence in cookies\n * - Redirecting unauthenticated users to sign-in page\n * - Allowing public routes to be accessed without authentication\n * - Mapping local auth routes to backend's fixed paths when using built-in auth\n *\n * **How Authentication Flow Works:**\n * 1. User visits protected route → Middleware checks for token\n * 2. No token → Redirects to sign-in (backend or local)\n * 3. User accesses auth page (e.g., /sign-in) → Redirects to backend with afterSignInUrl as redirect target\n * 4. After sign-in → Backend redirects to `yourapp.com/afterSignInUrl?access_token=xxx&user_id=xxx...`\n * 5. Middleware detects `access_token` in URL → Stores in HTTP-only cookie → Cleans URL → Allows access\n * 6. SDK also detects token from URL → Stores in localStorage → Updates auth state\n *\n * **Important Notes:**\n * - This middleware only checks if a token exists, it doesn't validate it\n * - Tokens from URL are automatically extracted and stored in cookies\n * - When `useBuiltInAuth: true`, local routes map to backend's fixed auth paths\n * - You can customize local route paths (e.g., `/login`) while backend paths remain fixed\n * - After successful auth, users are redirected to `afterSignInUrl` (default: `/`), not back to the auth page\n *\n * @param config - Middleware configuration\n * @returns Next.js middleware function\n *\n * @example\n * ```ts\n * // middleware.ts - Using built-in auth\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\n *\n * export default InsforgeMiddleware({\n * baseUrl: process.env.INSFORGE_BASE_URL!,\n * publicRoutes: ['/', '/about'],\n * afterSignInUrl: '/', // Redirect here after successful auth\n * useBuiltInAuth: true,\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\n * };\n * ```\n *\n * @example\n * ```ts\n * // middleware.ts - Custom local auth pages with custom paths\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\n *\n * export default InsforgeMiddleware({\n * baseUrl: process.env.INSFORGE_BASE_URL!,\n * publicRoutes: ['/login', '/register', '/', '/about'],\n * signInUrl: '/login',\n * signUpUrl: '/register',\n * afterSignInUrl: '/dashboard',\n * useBuiltInAuth: false,\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\n * };\n * ```\n *\n * @example\n * ```ts\n * // middleware.ts - Built-in auth with custom auth route paths\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\n *\n * export default InsforgeMiddleware({\n * baseUrl: 'https://your-backend.com',\n * signInUrl: '/login',\n * signUpUrl: '/register',\n * forgotPasswordUrl: '/forgot',\n * afterSignInUrl: '/dashboard',\n * useBuiltInAuth: true,\n * });\n * ```\n */\nexport const InsforgeMiddleware = (config: InsforgeMiddlewareConfig) => {\n const {\n baseUrl,\n publicRoutes = ['/'],\n signInUrl = '/sign-in',\n signUpUrl = '/sign-up',\n forgotPasswordUrl = '/forgot-password',\n afterSignInUrl = '/',\n useBuiltInAuth = true,\n } = config;\n\n return function middleware(request: NextRequest) {\n const { pathname, searchParams } = request.nextUrl;\n\n // STEP 1: Check if URL contains access_token (from backend redirect after auth)\n const accessToken = searchParams.get('access_token');\n const userId = searchParams.get('user_id');\n const email = searchParams.get('email');\n const name = searchParams.get('name');\n\n if (accessToken && userId && email) {\n // Token detected in URL - store it in HTTP-only cookies\n const response = NextResponse.next();\n const cookieOptions = getBaseCookieOptions();\n\n // Set session cookie (access token)\n response.cookies.set(COOKIE_NAMES.SESSION, accessToken, cookieOptions);\n\n // Set user identity cookie (basic user info for SSR)\n response.cookies.set(\n COOKIE_NAMES.USER,\n serializeUserCookie({ id: userId, email, name: name || undefined }),\n cookieOptions\n );\n\n return response;\n }\n\n // STEP 2: Handle built-in auth redirects for authentication pages\n // Map local auth routes to backend's fixed auth pages\n if (useBuiltInAuth) {\n const authRouteMapping: Record<string, string> = {\n [signInUrl]: '/auth/sign-in',\n [signUpUrl]: '/auth/sign-up',\n [forgotPasswordUrl]: '/auth/forgot-password',\n };\n\n const backendAuthPath = authRouteMapping[pathname];\n if (backendAuthPath) {\n // Redirect to afterSignInUrl after successful authentication\n const redirectUrl = new URL(afterSignInUrl, request.url).toString();\n const backendAuthUrl = new URL(backendAuthPath, baseUrl);\n backendAuthUrl.searchParams.set('redirect', redirectUrl);\n return NextResponse.redirect(backendAuthUrl.toString());\n }\n }\n\n // STEP 3: Check if route is public\n const isPublicRoute = publicRoutes.some((route) => {\n if (route.endsWith('*')) {\n // Wildcard route: /admin/* matches /admin/anything\n return pathname.startsWith(route.slice(0, -1));\n }\n // Exact match or starts with route path\n return pathname === route || pathname.startsWith(route + '/');\n });\n\n if (isPublicRoute) {\n return NextResponse.next();\n }\n\n // STEP 4: Check for authentication token in cookies\n const token = request.cookies.get(COOKIE_NAMES.SESSION)?.value;\n\n if (!token) {\n // No token found, redirect to sign-in\n if (useBuiltInAuth) {\n // Built-in auth: redirect to backend's /auth/sign-in page\n // Backend will redirect back to current URL with token\n const backendSignInUrl = new URL('/auth/sign-in', baseUrl);\n backendSignInUrl.searchParams.set('redirect', request.url);\n return NextResponse.redirect(backendSignInUrl);\n } else {\n // Custom auth: redirect to local sign-in page\n const localSignInUrl = new URL(signInUrl, request.url);\n localSignInUrl.searchParams.set('redirect', pathname);\n return NextResponse.redirect(localSignInUrl);\n }\n }\n\n // Token exists in cookie, allow request to continue\n return NextResponse.next();\n };\n};\n"],"mappings":"AAAA,SAAsB,oBAAoB;AAC1C,SAAS,cAAc,sBAAsB,2BAA2B;AAoIjE,MAAM,qBAAqB,CAAC,WAAqC;AACtE,QAAM;AAAA,IACJ;AAAA,IACA,eAAe,CAAC,GAAG;AAAA,IACnB,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,EACnB,IAAI;AAEJ,SAAO,SAAS,WAAW,SAAsB;AAC/C,UAAM,EAAE,UAAU,aAAa,IAAI,QAAQ;AAG3C,UAAM,cAAc,aAAa,IAAI,cAAc;AACnD,UAAM,SAAS,aAAa,IAAI,SAAS;AACzC,UAAM,QAAQ,aAAa,IAAI,OAAO;AACtC,UAAM,OAAO,aAAa,IAAI,MAAM;AAEpC,QAAI,eAAe,UAAU,OAAO;AAElC,YAAM,WAAW,aAAa,KAAK;AACnC,YAAM,gBAAgB,qBAAqB;AAG3C,eAAS,QAAQ,IAAI,aAAa,SAAS,aAAa,aAAa;AAGrE,eAAS,QAAQ;AAAA,QACf,aAAa;AAAA,QACb,oBAAoB,EAAE,IAAI,QAAQ,OAAO,MAAM,QAAQ,OAAU,CAAC;AAAA,QAClE;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAIA,QAAI,gBAAgB;AAClB,YAAM,mBAA2C;AAAA,QAC/C,CAAC,SAAS,GAAG;AAAA,QACb,CAAC,SAAS,GAAG;AAAA,QACb,CAAC,iBAAiB,GAAG;AAAA,MACvB;AAEA,YAAM,kBAAkB,iBAAiB,QAAQ;AACjD,UAAI,iBAAiB;AAEnB,cAAM,cAAc,IAAI,IAAI,gBAAgB,QAAQ,GAAG,EAAE,SAAS;AAClE,cAAM,iBAAiB,IAAI,IAAI,iBAAiB,OAAO;AACvD,uBAAe,aAAa,IAAI,YAAY,WAAW;AACvD,eAAO,aAAa,SAAS,eAAe,SAAS,CAAC;AAAA,MACxD;AAAA,IACF;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,aAAa,OAAO,GAAG;AAEzD,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