# 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 <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:

```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

- 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)
