"use client"; import { useState } from "react"; import { Lock } from "lucide-react"; import { setLocalAuthToken } from "@/auth/localAuth"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; const LOCAL_AUTH_TOKEN_MIN_LENGTH = 50; async function validateLocalToken(token: string): Promise { const rawBaseUrl = process.env.NEXT_PUBLIC_API_URL; if (!rawBaseUrl) { return "NEXT_PUBLIC_API_URL is not set."; } const baseUrl = rawBaseUrl.replace(/\/+$/, ""); let response: Response; try { response = await fetch(`${baseUrl}/api/v1/users/me`, { method: "GET", headers: { Authorization: `Bearer ${token}`, }, }); } catch { return "Unable to reach backend to validate token."; } if (response.ok) { return null; } if (response.status === 401 || response.status === 403) { return "Token is invalid."; } return `Unable to validate token (HTTP ${response.status}).`; } type LocalAuthLoginProps = { onAuthenticated?: () => void; }; const defaultOnAuthenticated = () => window.location.reload(); export function LocalAuthLogin({ onAuthenticated }: LocalAuthLoginProps) { const [token, setToken] = useState(""); const [error, setError] = useState(null); const [isValidating, setIsValidating] = useState(false); const handleSubmit = async (event: React.FormEvent) => { event.preventDefault(); const cleaned = token.trim(); if (!cleaned) { setError("Bearer token is required."); return; } if (cleaned.length < LOCAL_AUTH_TOKEN_MIN_LENGTH) { setError( `Bearer token must be at least ${LOCAL_AUTH_TOKEN_MIN_LENGTH} characters.`, ); return; } setIsValidating(true); const validationError = await validateLocalToken(cleaned); setIsValidating(false); if (validationError) { setError(validationError); return; } setLocalAuthToken(cleaned); setError(null); (onAuthenticated ?? defaultOnAuthenticated)(); }; return (
Self-host mode

Local Authentication

Enter your access token to unlock Mission Control.

setToken(event.target.value)} placeholder="Paste token" autoFocus disabled={isValidating} className="font-mono" />
{error ? (

{error}

) : (

Token must be at least {LOCAL_AUTH_TOKEN_MIN_LENGTH} characters.

)}
); }