diff --git a/app/api/auth/route.ts b/app/api/auth/route.ts index a5ccb20..cb705ae 100644 --- a/app/api/auth/route.ts +++ b/app/api/auth/route.ts @@ -1,5 +1,4 @@ import { NextResponse } from 'next/server' -import { cookies } from 'next/headers' import * as crypto from 'crypto' const SECRET = process.env.APP_SECRET || 'smart-home-default-secret-change-me' @@ -24,7 +23,7 @@ export async function POST(req: Request) { secure: true, sameSite: 'strict', path: '/', - maxAge: 60 * 60 * 24 * 365, // 1 year — tablet stays logged in + maxAge: 60 * 60 * 24 * 365, }) return res diff --git a/middleware.ts b/middleware.ts index 5e33f80..a724a1f 100644 --- a/middleware.ts +++ b/middleware.ts @@ -1,11 +1,18 @@ import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' -import * as crypto from 'crypto' -export function middleware(request: NextRequest) { +async function hmacSha256(secret: string, message: string): Promise { + 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 - // Allow auth API and static assets if ( pathname.startsWith('/api/auth') || pathname.startsWith('/_next') || @@ -18,15 +25,12 @@ export function middleware(request: NextRequest) { 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 = crypto.createHmac('sha256', secret).update(pin).digest('hex') + const expectedToken = await hmacSha256(secret, pin) if (token !== expectedToken) { - // For API routes, return 401 if (pathname.startsWith('/api/')) { return NextResponse.json({ error: 'unauthorized' }, { status: 401 }) } - - // For page requests, rewrite to show login (handled client-side) const url = request.nextUrl.clone() url.searchParams.set('locked', '1') return NextResponse.rewrite(url)