status-page-auth

star 2

Single-password admin authentication for this status-page app. Use this skill whenever working on login, sessions, the session cookie, middleware route protection, or the Node-vs-Edge runtime split for auth. Trigger on phrases like "protect the admin", "login", "session cookie", "middleware auth", "verify the session", "admin password", or anything touching lib/auth.ts, lib/auth-edge.ts, or middleware.ts. Apply automatically when building or changing authentication here.

nooblk-98 By nooblk-98 schedule Updated 6/6/2026

name: status-page-auth description: > Single-password admin authentication for this status-page app. Use this skill whenever working on login, sessions, the session cookie, middleware route protection, or the Node-vs-Edge runtime split for auth. Trigger on phrases like "protect the admin", "login", "session cookie", "middleware auth", "verify the session", "admin password", or anything touching lib/auth.ts, lib/auth-edge.ts, or middleware.ts. Apply automatically when building or changing authentication here.

Status Page Auth (single password)

There is one admin, protected by a single password and a signed session cookie. No users table.

The Node/Edge split (critical)

Next.js middleware.ts runs in the Edge runtime — it has Web Crypto but no sqlite3 and no Node crypto. Importing either into middleware breaks the build. Therefore auth is split into two files:

  • lib/auth.ts (Node runtime, used by route handlers only):
    • hashPassword(pw) / verifyPassword(pw, hash) via Node crypto.scrypt + timingSafeEqual.
    • createSession()jose new SignJWT({ role:'admin' }).setProtectedHeader({alg:'HS256'}).setExpirationTime('7d').sign(secret).
    • SESSION_COOKIE = 'sp_session', plus a helper to build the Set-Cookie options.
  • lib/auth-edge.ts (Edge-safe, imported ONLY by middleware.ts):
    • verifySession(token)jose.jwtVerify(token, secret); returns boolean. No DB, no Node crypto.
    • jose works in Edge because it uses Web Crypto — this is why we use jose instead of Node HMAC.

The signing secret comes from process.env.SESSION_SECRET (available in both runtimes). It MUST be stable across restarts or all sessions invalidate.

middleware.ts

export const config = { matcher: ['/admin/:path*', '/api/admin/:path*'] };
  • Allow /admin/login and /api/admin/auth/login through unauthenticated (entry points).
  • Read the sp_session cookie → verifySession. On failure: /api/admin/*401 JSON; page paths → NextResponse.redirect(new URL('/admin/login', req.url)).

Flows

  • Login POST /api/admin/auth/login {password}getAdminAuth() resolves the expected credential (DB admin.passwordHash first, else env.ADMIN_PASSWORD) → verify → createSession() → set cookie HttpOnly; SameSite=Lax; Path=/; Secure (prod); Max-Age=7d.
  • Logout POST /api/admin/auth/logout → clear cookie (Max-Age=0).

Bootstrap rules

  • If no DB password hash is set, accept env.ADMIN_PASSWORD (timing-safe compare).
  • If neither a DB hash nor ADMIN_PASSWORD is set, the login page shows a "set ADMIN_PASSWORD" notice and blank-password login is rejected.
  • Setting a password in the admin settings stores a scrypt hash in settings.admin and takes precedence over env.
Install via CLI
npx skills add https://github.com/nooblk-98/status-page --skill status-page-auth
Repository Details
star Stars 2
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator