- JWT via jose (HS256, 7d expiry) - Login API: POST /api/auth/login → returns token - Verify API: GET /api/auth/me - Middleware checks Bearer header or cookie - Token stored in localStorage + cookie (for SSR) - Authentik button (disabled, placeholder) - Auth headers auto-added to API requests
28 lines
800 B
TypeScript
28 lines
800 B
TypeScript
import { SignJWT, jwtVerify } from "jose";
|
|
|
|
const JWT_SECRET = new TextEncoder().encode(process.env.JWT_SECRET || "team-board-dev-secret-change-me");
|
|
const TOKEN_EXPIRY = "7d";
|
|
|
|
export interface TokenPayload {
|
|
sub: string; // username
|
|
name: string; // display name
|
|
provider: string; // "local" | "authentik"
|
|
}
|
|
|
|
export async function createToken(payload: TokenPayload): Promise<string> {
|
|
return new SignJWT({ ...payload })
|
|
.setProtectedHeader({ alg: "HS256" })
|
|
.setIssuedAt()
|
|
.setExpirationTime(TOKEN_EXPIRY)
|
|
.sign(JWT_SECRET);
|
|
}
|
|
|
|
export async function verifyToken(token: string): Promise<TokenPayload | null> {
|
|
try {
|
|
const { payload } = await jwtVerify(token, JWT_SECRET);
|
|
return payload as unknown as TokenPayload;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|