UNPKG

saget-auth-middleware

Version:

SSO Middleware dengan dukungan localStorage untuk validasi authentifikasi domain malinau.go.id dan semua subdomain pada aplikasi Next.js 14 & 15

240 lines (205 loc) • 7.63 kB
import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const envTemplate = `# ADD Config For SSO Intergrations To SAGET MALINAU # SSO Configuration SSO_LOGIN_URL=https://sso.malinau.go.id/login SSO_APP_KEY=r9k2m5x8v4n7q3w6t1y0z8h5j2l4c9p1 SSO_JWT_SECRET=your-actual-jwt-secret-here SSO_JWT_REFRESH_SECRET=your-actual-refresh-secret-here SSO_API_URL=https://sso.malinau.go.id/api # Cookie Configuration COOKIE_ACCESS_TOKEN_NAME=sso_access_token COOKIE_REFRESH_TOKEN_NAME=sso_refresh_token COOKIE_DOMAIN=.malinau.go.id # Redirect Configuration NEXT_REDIRECT_URL=http://localhost:3000 NEXT_PUBLIC_REDIRECT_URL=http://localhost:3000 # Public Environment Variables NEXT_PUBLIC_COOKIE_ACCESS_TOKEN_NAME=sso_access_token NEXT_PUBLIC_COOKIE_REFRESH_TOKEN_NAME=sso_refresh_token NEXT_PUBLIC_COOKIE_DOMAIN=.malinau.go.id NEXT_PUBLIC_APP_KEY=r9k2m5x8v4n7q3w6t1y0z8h5j2l4c9p1 NEXT_PUBLIC_API_URL_CLIENT_SIDE=https://sso.malinau.go.id/api # LocalStorage Keys LOCALSTORAGE_ACCESS_TOKEN_KEY=x-accessToken:sso.malinau.go.id LOCALSTORAGE_REFRESH_TOKEN_KEY=x-refreshToken:sso.malinau.go.id `; const middlewareJSTemplate = `// middleware.js import SSOMiddleware from 'saget-auth-middleware'; export function middleware(request) { // Skip authentication for public routes if (request.nextUrl.pathname.startsWith('/api/auth') || request.nextUrl.pathname.startsWith('/login') || request.nextUrl.pathname === '/') { return; } return SSOMiddleware.withSSOValidation((req) => { // Middleware berhasil, lanjutkan ke route console.log('User authenticated:', req.user?.email); console.log('User role:', req.role); console.log('User subrole:', req.subrole); })(request); } export const config = { matcher: [ /* * Match all request paths except for the ones starting with: * - api/auth (auth routes) * - _next/static (static files) * - _next/image (image optimization files) * - favicon.ico (favicon file) */ '/((?!api/auth|_next/static|_next/image|favicon.ico).*)', ], }; `; const middlewareTSTemplate = `// middleware.ts import { NextRequest, NextResponse } from 'next/server'; import SSOMiddleware from 'saget-auth-middleware'; // Type definitions for SSO payload interface UserProfile { id: string; userId: string; name: string; externalId: string | null; address: string; village: string | null; district: string | null; city: string; province: string; } interface UserApplication { id: string; applicationName: string; applicationKey: string; organization: string; organizationAddress: string | null; organizationContact: string | null; url: string; callbackUrl: string; isPublic: boolean; status: string; createdAt: string; updatedAt: string; role: string; subrole: string; } interface SSOPayload { user: UserProfile; application: UserApplication; role: string; subrole: string; iat: number; exp: number; } // Extend NextRequest to include SSO payload declare module 'next/server' { interface NextRequest { user?: UserProfile; application?: UserApplication; role?: string; subrole?: string; ssoPayload?: SSOPayload; } } export function middleware(request: NextRequest): NextResponse | void { // Skip authentication for public routes if (request.nextUrl.pathname.startsWith('/api/auth') || request.nextUrl.pathname.startsWith('/login') || request.nextUrl.pathname === '/') { return; } return SSOMiddleware.withSSOValidation((req: NextRequest) => { // Middleware berhasil, lanjutkan ke route console.log('User authenticated:', req.user?.name); console.log('User email:', req.user?.userId); console.log('User role:', req.role); console.log('User subrole:', req.subrole); console.log('Application:', req.application?.applicationName); return NextResponse.next(); })(request); } export const config = { matcher: [ '/((?!api/auth|_next/static|_next/image|favicon.ico|public).*)', ], }; `; function detectProjectType(projectRoot) { const tsconfigPath = path.join(projectRoot, 'tsconfig.json'); const packageJsonPath = path.join(projectRoot, 'package.json'); // Check if tsconfig.json exists if (fs.existsSync(tsconfigPath)) { return 'typescript'; } // Check package.json for TypeScript dependencies if (fs.existsSync(packageJsonPath)) { try { const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); const deps = { ...packageJson.dependencies, ...packageJson.devDependencies }; if (deps.typescript || deps['@types/node'] || deps['@types/react']) { return 'typescript'; } } catch (error) { console.warn('Could not parse package.json, defaulting to JavaScript'); } } return 'javascript'; } function setupEnvironment() { try { // Get the project root (where package.json is located) const projectRoot = process.cwd(); const envPath = path.join(projectRoot, '.env.local'); const envExamplePath = path.join(projectRoot, '.env.example'); // Detect project type const projectType = detectProjectType(projectRoot); const isTypeScript = projectType === 'typescript'; const middlewareFileName = isTypeScript ? 'middleware.ts' : 'middleware.js'; const middlewarePath = path.join(projectRoot, middlewareFileName); const middlewareTemplate = isTypeScript ? middlewareTSTemplate : middlewareJSTemplate; console.log('šŸš€ Setting up SAGET SSO Middleware...'); console.log(`šŸ“ Detected project type: ${projectType.toUpperCase()}`); // Check if .env.local already exists if (!fs.existsSync(envPath)) { fs.writeFileSync(envPath, envTemplate); console.log('āœ… Created .env.local with SSO configuration'); } else { console.log('ā„¹ļø .env.local already exists, skipping creation'); console.log('šŸ“ Please add the following variables to your .env.local:'); console.log(envTemplate); } // Always create/update .env.example fs.writeFileSync(envExamplePath, envTemplate); console.log('āœ… Created/updated .env.example with SSO configuration'); // Create middleware file if it doesn't exist if (!fs.existsSync(middlewarePath)) { fs.writeFileSync(middlewarePath, middlewareTemplate); console.log(`āœ… Created ${middlewareFileName} with SSO configuration`); } else { console.log(`ā„¹ļø ${middlewareFileName} already exists, skipping creation`); } console.log('\nšŸ“‹ Next steps:'); console.log('1. āœļø Update the values in .env.local with your actual SSO credentials'); console.log(`2. šŸ”§ Customize ${middlewareFileName} according to your needs`); if (isTypeScript) { console.log('3. šŸ“¦ Make sure you have @types/node installed for TypeScript support'); console.log('4. šŸš€ Start your Next.js development server'); } else { console.log('3. šŸš€ Start your Next.js development server'); } console.log('\nšŸ“– For detailed setup instructions, visit: https://github.com/your-repo/saget-auth-midleware'); console.log('\nšŸŽ‰ SAGET SSO Middleware setup completed!'); } catch (error) { console.error('āŒ Error setting up environment:', error.message); process.exit(1); } } // Only run setup if this script is executed directly (not imported) if (import.meta.url === `file://\${process.argv[1]}`) { setupEnvironment(); } export { setupEnvironment };