# 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: ```go // 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**: ```json POST /api/auth/login { "login": "user@example.com", "password": "SecureP@ss123!" } ``` **Response**: ```json { "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: ```bash curl -H "Authorization: Bearer " \ 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: ```json POST /api/auth/refresh { "refresh_token": "uuid-refresh-token" } ``` **Response**: ```json { "access_token": "new-jwt-token", "token_type": "Bearer", "expires_in": 604800 } ``` ### 4. Logout Revokes the refresh token on the server: ```json 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: ```json { "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)