fix: use Web Crypto API in middleware (Edge Runtime compat)
All checks were successful
Deploy / deploy (push) Successful in 2m34s
All checks were successful
Deploy / deploy (push) Successful in 2m34s
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
import { NextResponse } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
import { cookies } from 'next/headers'
|
|
||||||
import * as crypto from 'crypto'
|
import * as crypto from 'crypto'
|
||||||
|
|
||||||
const SECRET = process.env.APP_SECRET || 'smart-home-default-secret-change-me'
|
const SECRET = process.env.APP_SECRET || 'smart-home-default-secret-change-me'
|
||||||
@@ -24,7 +23,7 @@ export async function POST(req: Request) {
|
|||||||
secure: true,
|
secure: true,
|
||||||
sameSite: 'strict',
|
sameSite: 'strict',
|
||||||
path: '/',
|
path: '/',
|
||||||
maxAge: 60 * 60 * 24 * 365, // 1 year — tablet stays logged in
|
maxAge: 60 * 60 * 24 * 365,
|
||||||
})
|
})
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
import { NextResponse } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
import type { NextRequest } 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<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
|
const { pathname } = request.nextUrl
|
||||||
|
|
||||||
// Allow auth API and static assets
|
|
||||||
if (
|
if (
|
||||||
pathname.startsWith('/api/auth') ||
|
pathname.startsWith('/api/auth') ||
|
||||||
pathname.startsWith('/_next') ||
|
pathname.startsWith('/_next') ||
|
||||||
@@ -18,15 +25,12 @@ export function middleware(request: NextRequest) {
|
|||||||
const token = request.cookies.get('auth_token')?.value
|
const token = request.cookies.get('auth_token')?.value
|
||||||
const pin = process.env.APP_PIN || '1234'
|
const pin = process.env.APP_PIN || '1234'
|
||||||
const secret = process.env.APP_SECRET || 'smart-home-default-secret-change-me'
|
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) {
|
if (token !== expectedToken) {
|
||||||
// For API routes, return 401
|
|
||||||
if (pathname.startsWith('/api/')) {
|
if (pathname.startsWith('/api/')) {
|
||||||
return NextResponse.json({ error: 'unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: 'unauthorized' }, { status: 401 })
|
||||||
}
|
}
|
||||||
|
|
||||||
// For page requests, rewrite to show login (handled client-side)
|
|
||||||
const url = request.nextUrl.clone()
|
const url = request.nextUrl.clone()
|
||||||
url.searchParams.set('locked', '1')
|
url.searchParams.set('locked', '1')
|
||||||
return NextResponse.rewrite(url)
|
return NextResponse.rewrite(url)
|
||||||
|
|||||||
Reference in New Issue
Block a user