47 lines
1.5 KiB
TypeScript
47 lines
1.5 KiB
TypeScript
import { NextResponse } from 'next/server'
|
|
import type { NextRequest } from 'next/server'
|
|
import { isDemoRequest } from '@encryptid/sdk/server/nextjs'
|
|
|
|
/**
|
|
* Middleware to protect /space routes.
|
|
*
|
|
* Client-side auth enforcement: the space page itself checks auth state via
|
|
* Zustand store. This middleware adds a cookie-based check for server-rendered
|
|
* requests — if no encryptid_token cookie is present on /space, redirect to
|
|
* the home page with a login hint.
|
|
*
|
|
* Demo spaces (ENCRYPTID_DEMO_SPACES env var) bypass auth.
|
|
*/
|
|
export function middleware(request: NextRequest) {
|
|
const { pathname } = request.nextUrl
|
|
|
|
// Only protect /space routes (not /tbff which is a public demo)
|
|
if (pathname.startsWith('/space')) {
|
|
// Demo spaces get anonymous access — SDK provides synthetic claims
|
|
if (isDemoRequest(request)) {
|
|
return NextResponse.next()
|
|
}
|
|
|
|
// Check for auth token in cookie (set by client after login)
|
|
const token = request.cookies.get('encryptid_token')?.value
|
|
|
|
// Also check Authorization header for API-style access
|
|
const authHeader = request.headers.get('authorization')
|
|
const bearerToken = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null
|
|
|
|
if (!token && !bearerToken) {
|
|
const url = request.nextUrl.clone()
|
|
url.pathname = '/'
|
|
url.searchParams.set('login', 'required')
|
|
url.searchParams.set('return', pathname)
|
|
return NextResponse.redirect(url)
|
|
}
|
|
}
|
|
|
|
return NextResponse.next()
|
|
}
|
|
|
|
export const config = {
|
|
matcher: ['/space/:path*'],
|
|
}
|