← back to Omega Watches 2

src/lib/auth.ts

85 lines

import { SignJWT, jwtVerify } from "jose";
import { compare, hash } from "bcryptjs";
import { cookies } from "next/headers";
import { NextRequest } from "next/server";

const JWT_SECRET = new TextEncoder().encode(
  process.env.JWT_SECRET || "omega-watches-2-enterprise-secret-key-2024"
);
const TOKEN_EXPIRY = "24h";
const COOKIE_NAME = "omega_session";

// Omega standalone credentials
const ADMIN_USERNAME = process.env.ADMIN_USERNAME || "admin";
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || "OmegaAdmin2024!";

export interface SessionPayload {
  userId: string;
  username: string;
  role: "admin" | "operator" | "auditor" | "viewer";
  iat: number;
  exp: number;
}

export async function verifyCredentials(
  username: string,
  password: string
): Promise<{ valid: boolean; role: string }> {
  if (username === ADMIN_USERNAME && password === ADMIN_PASSWORD) {
    return { valid: true, role: "admin" };
  }
  return { valid: false, role: "" };
}

export async function createSession(
  userId: string,
  username: string,
  role: string
): Promise<string> {
  const token = await new SignJWT({ userId, username, role })
    .setProtectedHeader({ alg: "HS256" })
    .setIssuedAt()
    .setExpirationTime(TOKEN_EXPIRY)
    .sign(JWT_SECRET);
  return token;
}

export async function verifySession(
  token: string
): Promise<SessionPayload | null> {
  try {
    const { payload } = await jwtVerify(token, JWT_SECRET);
    return payload as unknown as SessionPayload;
  } catch {
    return null;
  }
}

export async function getSession(
  request: NextRequest
): Promise<SessionPayload | null> {
  const token =
    request.cookies.get(COOKIE_NAME)?.value ||
    request.headers.get("authorization")?.replace("Bearer ", "");
  if (!token) return null;
  return verifySession(token);
}

export async function requireAuth(
  request: NextRequest
): Promise<SessionPayload> {
  const session = await getSession(request);
  if (!session) {
    throw new Error("Unauthorized");
  }
  return session;
}

export function requireRole(session: SessionPayload, roles: string[]): void {
  if (!roles.includes(session.role)) {
    throw new Error(`Forbidden: requires one of [${roles.join(", ")}]`);
  }
}

export { COOKIE_NAME };