Skip to content

Authentication

SideSeat uses a token-based authentication system that secures the web UI while remaining easy to use for local development.

  1. Server starts → Generates a bootstrap token and prints URL to terminal
  2. User clicks URL → Browser exchanges bootstrap token for JWT session
  3. JWT stored in cookie → HttpOnly, SameSite=Strict cookie for security
  4. Protected routes → API endpoints validate JWT on each request
Terminal window
# Start with authentication (default)
sideseat start
# Output:
# SideSeat v1.0.4
# ➜ Local: http://127.0.0.1:5001/ui?token=abc123...

Click the URL with the token to authenticate automatically.

For development or trusted environments, authentication can be disabled:

Terminal window
# CLI flag
sideseat start --no-auth
# Environment variable
SIDESEAT_AUTH_ENABLED=false sideseat start

Or in configuration file:

{
"auth": {
"enabled": false
}
}
Terminal URL: http://localhost:5001/ui?token=<bootstrap_token>
Frontend: POST /api/v1/auth/exchange { token: "<bootstrap_token>" }
Server: Validates token, returns JWT in Set-Cookie header
Browser: Stores HttpOnly cookie, redirects to app
Browser: GET /api/v1/protected
Cookie: sideseat_session=<jwt>
Server: Validates JWT signature and expiration
Response: 200 OK (valid) or 401 Unauthorized (invalid/expired)

Exchange a bootstrap token for a JWT session.

Request:

{ "token": "bootstrap_token_here" }

Success Response (200):

{ "success": true, "message": "Authentication successful" }

Plus Set-Cookie: sideseat_session=<jwt>; HttpOnly; SameSite=Strict; Path=/api

Error Response (401):

{
"error": "unauthorized",
"code": "BOOTSTRAP_INVALID",
"message": "Invalid bootstrap token"
}

Check current authentication status.

Response:

{
"authenticated": true,
"auth_method": "bootstrap",
"expires_at": "2025-02-24T12:00:00Z"
}

Clear the session cookie.

Response:

{ "success": true, "message": "Logged out successfully" }
FeatureImplementation
Token StorageJWT signing key in OS keychain via SecretManager
Cookie SecurityHttpOnly, SameSite=Strict, Path=/api
Token ValidationConstant-time comparison (timing attack resistant)
Session Expiry30-day JWT lifetime
CSRF ProtectionSameSite cookie + Origin header validation
{
"sub": "local",
"iat": 1703001234,
"exp": 1705593234,
"jti": "unique-uuid-v4",
"auth_method": "bootstrap"
}
ClaimDescription
subSubject identifier (“local” for bootstrap auth)
iatIssued at timestamp
expExpiration timestamp (30 days from issue)
jtiUnique JWT ID for tracking
auth_methodAuthentication method used

All authentication errors return 401 with a structured response:

{
"error": "unauthorized",
"code": "ERROR_CODE",
"message": "Human-readable message"
}
CodeDescription
AUTH_REQUIREDNo session cookie present
TOKEN_EXPIREDJWT has expired
TOKEN_INVALIDInvalid JWT signature
BOOTSTRAP_INVALIDInvalid bootstrap token
ORIGIN_NOT_ALLOWEDRequest from disallowed origin
use sideseat::auth::{require_auth, AuthManager};
use axum::{Router, middleware, routing::get};
let auth_manager = Arc::new(AuthManager::init(&secrets, true).await?);
let protected_routes = Router::new()
.route("/protected", get(handler))
.layer(middleware::from_fn_with_state(
auth_manager.clone(),
require_auth
));
import { useAuth } from "@/auth/context";
function MyComponent() {
const { authenticated, loading, login, logout } = useAuth();
if (loading) return <div>Loading...</div>;
if (!authenticated) return <div>Please authenticate</div>;
return <div>Welcome!</div>;
}
import { AuthGuard } from "@/auth/guard";
<AuthGuard>
<ProtectedPage />
</AuthGuard>
import { fetchAPI, AuthError } from "@/api/client";
try {
const data = await fetchAPI("/protected");
} catch (e) {
if (e instanceof AuthError) {
// Redirect to login
}
}
  1. Always use HTTPS in production - Cookies are sent in clear text over HTTP
  2. Click “Always Allow” - On macOS, grant keychain access permanently
  3. Don’t share terminal URLs - Bootstrap tokens grant access
  4. Monitor session expiry - 30-day tokens should be refreshed periodically
  5. Use —no-auth carefully - Only in trusted, isolated environments