Files
bookhoard/docs/developer/api/authentication/overview.md
T
john-okeefe 2a7ac881fd docs(user): align sync and user guides with current device support
- sync-guide: only Web and KOReader are fully supported; move Kobo to
  coming soon, drop fake Q2-Q4 2026 release dates for mobile/Kindle/
  Remarkable, and describe the plugin + server-approval registration
  flow instead of QR-code/URL approval
- sync-guide: remove cellular/mobile-app advice from battery and
  best-practice sections, correct the Calibre compatibility FAQ, update
  the changelog to reflect shipped vs. pending sync features, and fix
  the license header (GPL-3.0, not MIT)
- user-guide: lead device setup with KOReader; mark the Kobo guide as
  coming soon
- calibre-integration: OPDS client list no longer implies native Kobo
  support
- auth overview: label the mobile-application token guidance as
  'coming later' since no mobile apps exist yet
2026-08-20 14:14:49 -04:00

4.1 KiB
Raw Blame History

Authentication Overview

Bookhoard uses JWT-based authentication with 7-day persistent sessions and refresh tokens for security.

Session Duration

All JWT tokens and refresh tokens are valid for 7 days from creation. This provides a Google-like persistent session experience.

  • JWT Access Token: Valid for 7 days
  • Refresh Token: Valid for 7 days
  • HTTP-only Cookie: Max-Age of 7 days (604800 seconds)

Implementation Details

Session durations are defined using constants to maintain a single source of truth:

// internal/handlers/auth.go
const (
    SessionDuration     = 7 * 24 * time.Hour // 7 days
)

// SessionDurationSec is computed from SessionDuration
var SessionDurationSec = int(SessionDuration.Seconds()) // 604800 seconds

No hardcoded values exist in the codebase. All timeout values use these constants:

  • JWT token exp claim: time.Now().Add(SessionDuration).Unix()
  • Cookie MaxAge: SessionDurationSec
  • API response expires_in: SessionDurationSec

Authentication Flow

1. Registration/Login

When a user registers or logs in:

  1. Server generates a JWT access token (valid for 7 days)
  2. Server creates a refresh token in the database (valid for 7 days)
  3. Server sets an HTTP-only cookie with the JWT token
  4. Server returns JSON response with both tokens and user profile

Request:

POST /api/auth/login
{
  "login": "user@example.com",
  "password": "SecureP@ss123!"
}

Response:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "uuid-refresh-token",
  "token_type": "Bearer",
  "expires_in": 604800,
  "user": {
    "id": "uuid",
    "email": "user@example.com",
    "username": "john",
    "role": "user"
  }
}

Set-Cookie Header:

Set-Cookie: token=eyJhbG...; Max-Age=604800; Path=/; HttpOnly

2. Making Authenticated Requests

Include the JWT token in the Authorization header:

curl -H "Authorization: Bearer <token>" \
  https://api.example.com/api/libraries

The server also checks for the token in the HTTP-only cookie automatically.

3. Token Refresh

When your access token expires (after 7 days), use the refresh token to get a new one:

POST /api/auth/refresh
{
  "refresh_token": "uuid-refresh-token"
}

Response:

{
  "access_token": "new-jwt-token",
  "token_type": "Bearer",
  "expires_in": 604800
}

4. Logout

Revokes the refresh token on the server:

POST /api/auth/logout
{
  "refresh_token": "uuid-refresh-token"
}

Session Expiration Handling

Web Browser Requests

When a user's session expires during page navigation:

  1. Server redirects to /login?session=expired
  2. Login page displays: "Your session has expired. Please log in again to continue."
  3. User re-authenticates and is redirected to their intended destination

API Requests

When an API call receives a 401 Unauthorized response:

{
  "error": "session_expired",
  "message": "Your session has expired. Please log in again."
}

The frontend toast.js interceptor:

  1. Clears invalid tokens from localStorage
  2. Shows an error toast notification
  3. Allows user to re-authenticate

Security Features

  • HTTP-only Cookies: Prevents XSS attacks on token cookies
  • Refresh Token Rotation: New refresh tokens issued on each refresh
  • 7-Day Expiration: Reasonable balance between security and convenience
  • Constants-Based Configuration: Single source of truth for session duration

Token Storage Recommendations

Browser Applications

  • Backend: Automatically manages HTTP-only cookie
  • Frontend: Store tokens in localStorage for API calls

Mobile Applications (coming later)

  • Store access token in secure storage (Keychain/Keystore)
  • Store refresh token in secure storage
  • Handle 401 responses by prompting user to re-authenticate

Constants Reference

All session durations use constants defined in:

  • internal/handlers/auth.go - SessionDuration, SessionDurationSec
  • internal/handlers/refresh_token.go - SessionDurationSec (mirrored)

Total value: 604800 seconds (7 days × 24 hours × 60 minutes × 60 seconds)