Understanding the Role of middleware.ts in LunaTV: Authentication and Route Protection

The middleware.ts file in LunaTV acts as a Next.js Edge Middleware gatekeeper that intercepts every incoming request to enforce authentication, skip static assets, and redirect unauthenticated users to login while returning 401 errors for API routes.

The src/middleware.ts file serves as the central security orchestrator for the MoonTechLab/LunaTV open-source media platform. Running at the Edge before any page or API handler executes, this middleware validates environment configuration, parses authentication cookies, and verifies cryptographic signatures to ensure only authorized users access protected content. It implements a dual-mode authentication system that supports both local password storage and HMAC-based signature verification.

Skipping Unprotected Static Assets

In src/middleware.ts, the shouldSkipAuth helper (lines 19-30) maintains application performance by whitelisting paths that never require authentication. This function checks the request pathname against static asset routes including /_next, /favicon.ico, /robots.txt, and other public files. When a match occurs, the middleware immediately returns NextResponse.next() to allow the request to proceed unchanged, preventing unnecessary authentication overhead for static resources.

Enforcing Password Configuration

Before processing any authentication logic, the middleware verifies that the PASSWORD environment variable is properly configured (lines 15-21). If this variable is missing or empty, every request receives a redirect to the /warning page, ensuring the LunaTV instance cannot be accessed in an insecure state. This safety check runs early in the middleware lifecycle to guarantee that administrators explicitly define access credentials before users can interact with the system.

Extracting Authentication Data

The getAuthInfoFromCookie function (line 24) in src/lib/auth.ts parses the incoming request cookies to extract authentication context. This helper returns an object containing username, password, and/or signature values depending on the active storage mode. If the middleware cannot locate valid authentication data in the cookies, it immediately triggers the handleAuthFailure routine (line 27) to terminate the request with appropriate access controls.

Supporting Dual Storage Modes

LunaTV's middleware.ts implements two distinct authentication strategies controlled by the NEXT_PUBLIC_STORAGE_TYPE environment variable:

Local-Storage Mode

When NEXT_PUBLIC_STORAGE_TYPE is set to localstorage, the middleware validates that the password stored in the cookie directly matches process.env.PASSWORD (lines 31-35). This mode stores the actual credentials client-side in an encrypted cookie, providing straightforward authentication suitable for trusted local networks.

Signature-Based Mode

For enhanced security, the signature mode stores only a username and HMAC signature in the cookie. The middleware uses the Web Crypto API through the verifySignature function (lines 38-56) to cryptographically validate the signature against the server-side secret. If the signature verification succeeds, the request proceeds to the protected resource; otherwise, the middleware falls back to handleAuthFailure.

Handling Authentication Failures

The handleAuthFailure function (lines 101-116) implements differentiated responses based on the request type. API routes receive a direct 401 Unauthorized response with appropriate headers, while browser requests are redirected to /login with a redirect query parameter preserving the original destination URL. This dual-behavior approach ensures that programmatic clients receive machine-readable status codes while human users experience seamless login flows.

Configuring the Middleware Matcher

The exported config.matcher (lines 33-38) defines precise URL patterns that trigger the middleware execution. This configuration explicitly excludes static asset routes, the login page, the warning page, and specific API endpoints from middleware processing. By limiting interception to relevant protected routes, LunaTV maintains optimal performance while ensuring comprehensive security coverage.

Practical Implementation Examples

Any page placed under the /dashboard route automatically inherits middleware protection without additional code:

// src/pages/dashboard.tsx
export default function Dashboard() {
  // This component only renders if middleware.ts validates the request
  return <div>Protected LunaTV Dashboard</div>;
}

API routes can rely on the same authentication layer. Invalid requests receive 401 responses before reaching the handler:

// src/pages/api/secret.ts
export default function handler(req, res) {
  // Execution reaches here only after middleware validation succeeds
  res.json({ secret: 'Luna TV secret data' });
}

Configure the authentication mode via environment variables:


# .env.local

# Option 1: Store password directly in cookie

NEXT_PUBLIC_STORAGE_TYPE=localstorage

# Option 2: Store only HMAC signature

NEXT_PUBLIC_STORAGE_TYPE=signature

The login page handles post-authentication redirects by reading the redirect query parameter:

// src/pages/login.tsx
import { useRouter } from 'next/router';

export default function Login() {
  const router = useRouter();
  const { redirect } = router.query;
  
  const handleSuccess = () => {
    router.push((redirect as string) ?? '/');
  };
  
  return <LoginForm onSuccess={handleSuccess} />;
}

Summary

  • src/middleware.ts operates as a Next.js Edge Middleware that executes before every page and API request in LunaTV.
  • The shouldSkipAuth function efficiently bypasses static assets like /_next and /favicon.ico to maintain performance.
  • Environment validation ensures the PASSWORD variable is configured, redirecting to /warning if missing.
  • getAuthInfoFromCookie extracts credentials from cookies, supporting both plaintext password and HMAC signature modes.
  • verifySignature uses the Web Crypto API to validate cryptographic signatures without exposing server secrets.
  • handleAuthFailure returns 401 for APIs and redirects browsers to /login with preserved destination URLs.
  • The config.matcher limits middleware execution to relevant routes, excluding public pages and static files.

Frequently Asked Questions

How does LunaTV middleware.ts handle unauthenticated API requests differently from page requests?

According to the MoonTechLab/LunaTV source code, the handleAuthFailure function (lines 101-116) detects the request type through URL pattern matching. API routes receive a 401 Unauthorized response with appropriate headers, while standard page requests trigger a redirect to /login with a redirect query parameter. This differentiation ensures REST clients receive proper HTTP status codes while web users experience a seamless authentication flow.

What happens if the PASSWORD environment variable is not set in LunaTV?

If process.env.PASSWORD is undefined, src/middleware.ts redirects every incoming request to the /warning page (lines 15-21). This prevents the LunaTV instance from operating in an insecure state by forcing administrators to configure authentication credentials before granting any access to the application interface or API endpoints.

Can LunaTV operate without cookies for authentication?

No, the LunaTV middleware fundamentally relies on cookies to transport authentication data. The getAuthInfoFromCookie function reads either a stored password or HMAC signature from the request cookies (line 24). Without this cookie data, the middleware cannot validate the session and will always trigger handleAuthFailure, making cookie-based authentication mandatory for all protected routes.

What is the difference between localstorage and signature modes in middleware.ts?

Local-storage mode stores the actual password value in the cookie and validates it against process.env.PASSWORD (lines 31-35), suitable for trusted local networks. Signature-based mode stores only a username and HMAC signature, verified using the Web Crypto API via verifySignature (lines 38-56), providing enhanced security by never transmitting the actual password to the client after initial authentication.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →