36 lines
1.2 KiB
TypeScript
36 lines
1.2 KiB
TypeScript
import { NextResponse } from 'next/server'
|
|
import type { NextRequest } from 'next/server'
|
|
|
|
async function hmacSha256(secret: string, message: string): Promise<string> {
|
|
const enc = new TextEncoder()
|
|
const key = await crypto.subtle.importKey(
|
|
'raw', enc.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']
|
|
)
|
|
const sig = await crypto.subtle.sign('HMAC', key, enc.encode(message))
|
|
return Array.from(new Uint8Array(sig)).map(b => b.toString(16).padStart(2, '0')).join('')
|
|
}
|
|
|
|
export async function middleware(request: NextRequest) {
|
|
const { pathname } = request.nextUrl
|
|
|
|
// Only protect API routes (except /api/auth)
|
|
if (!pathname.startsWith('/api/') || pathname.startsWith('/api/auth')) {
|
|
return NextResponse.next()
|
|
}
|
|
|
|
const token = request.cookies.get('auth_token')?.value
|
|
const pin = process.env.APP_PIN || '1234'
|
|
const secret = process.env.APP_SECRET || 'smart-home-default-secret-change-me'
|
|
const expectedToken = await hmacSha256(secret, pin)
|
|
|
|
if (token !== expectedToken) {
|
|
return NextResponse.json({ error: 'unauthorized' }, { status: 401 })
|
|
}
|
|
|
|
return NextResponse.next()
|
|
}
|
|
|
|
export const config = {
|
|
matcher: ['/api/:path*'],
|
|
}
|