# Security Documentation - OAuth Plugin

This document outlines the security measures, best practices, and requirements for the OAuth Plugin.

## Table of Contents

1. [Security Features](#security-features)
2. [HTTPS Requirement](#https-requirement)
3. [CSRF Protection](#csrf-protection)
4. [Token Encryption](#token-encryption)
5. [Secrets Management](#secrets-management)
6. [JWT Token Security](#jwt-token-security)
7. [Session Management](#session-management)
8. [Input Validation](#input-validation)
9. [Error Handling](#error-handling)
10. [Security Checklist](#security-checklist)

## Security Features

The OAuth Plugin implements multiple layers of security to protect user authentication and OAuth tokens:

-   **CSRF Protection**: State parameter validation using cryptographically secure random generation
-   **Token Encryption**: AES-256-GCM encryption for OAuth tokens stored in the database
-   **Session Expiration**: Automatic cleanup of expired OAuth sessions via MongoDB TTL indexes
-   **Input Validation**: Comprehensive validation of all handler inputs
-   **Secure Error Messages**: User-friendly errors that don't expose sensitive information
-   **JWT Integration**: Secure JWT token generation via JWT Auth Plugin

## HTTPS Requirement

**CRITICAL: OAuth callback URLs MUST use HTTPS in production environments.**

### Why HTTPS is Required

-   OAuth authorization codes are transmitted in URL query parameters
-   Without HTTPS, these codes can be intercepted via man-in-the-middle attacks
-   OAuth access tokens are sensitive credentials that must be encrypted in transit

### Configuration

```typescript
oauthPlugin({
    providers: {
        github: {
            // PRODUCTION - HTTPS required
            callbackUrl: "https://myapp.com/oauth/github/callback",

            // DEVELOPMENT ONLY - HTTP acceptable for localhost
            // callbackUrl: 'http://localhost:3000/oauth/github/callback',
        },
    },
});
```

### OAuth Provider Requirements

Both GitHub and Google require HTTPS callback URLs for production applications. HTTP is only allowed for:

-   Localhost development: `http://localhost:*`
-   Local IP addresses: `http://127.0.0.1:*`

## CSRF Protection

The plugin implements CSRF (Cross-Site Request Forgery) protection using the OAuth state parameter.

### How It Works

1. **State Generation**: When initiating OAuth flow, plugin generates a cryptographically secure 32-byte random state parameter
2. **State Storage**: State is stored in MongoDB OAuth session with 10-minute TTL
3. **State Validation**: On callback, plugin validates the returned state matches stored state using constant-time comparison
4. **Session Cleanup**: OAuth session is deleted after successful validation to prevent reuse

### Implementation Details

```typescript
// State generation using crypto.randomBytes(32)
const state = generateState(); // Returns 64-character hex string

// Constant-time comparison to prevent timing attacks
const isValid = validateState(providedState, storedState);
```

### What This Prevents

-   CSRF attacks where attacker tricks user into authorizing attacker's account
-   Session fixation attacks
-   Replay attacks using old authorization codes

## Token Encryption

OAuth access tokens and refresh tokens are encrypted before storage in MongoDB using AES-256-GCM.

### Encryption Algorithm

-   **Algorithm**: AES-256-GCM (Galois/Counter Mode)
-   **Key Length**: 256 bits
-   **IV Length**: 128 bits (randomly generated per encryption)
-   **Authentication Tag**: 128 bits (for integrity verification)
-   **Key Derivation**: PBKDF2 with 100,000 iterations using SHA-256

### Encrypted Token Format

```
salt:iv:authTag:encryptedData
```

All components are hex-encoded for storage.

### Why Encryption is Important

-   OAuth tokens provide access to user's data on external platforms (GitHub, Google)
-   If database is compromised, encrypted tokens cannot be used by attackers
-   Encryption is required by security compliance standards (GDPR, SOC 2)

### Configuration

```typescript
oauthPlugin({
    storeTokens: true, // Enable token storage (encrypted)
    providers: {
        github: {
            clientSecret: process.env.GITHUB_CLIENT_SECRET, // Used as encryption key
        },
    },
});
```

### Encryption Secret

The plugin uses the OAuth provider's `clientSecret` as the encryption secret. Requirements:

-   Minimum 32 characters length
-   Should be cryptographically secure
-   Never commit to version control
-   Rotate periodically (requires re-encryption of existing tokens)

## Secrets Management

### Required Secrets

1. **OAuth Client Secrets**: From OAuth provider (GitHub, Google)
2. **JWT Auth Plugin Secret**: For generating JWT tokens
3. **MongoDB Connection String**: Database credentials

### Best Practices

1. **Environment Variables**: Store all secrets in environment variables

```bash
# .env file (DO NOT commit to git)
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret_at_least_32_chars
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret_at_least_32_chars
JWT_SECRET=your_jwt_secret_at_least_32_chars
MONGODB_URI=mongodb://user:pass@host:port/db
```

2. **Secret Management Services**: For production, use services like:

    - AWS Secrets Manager
    - HashiCorp Vault
    - Azure Key Vault
    - Google Cloud Secret Manager

3. **Git Ignore**: Ensure `.env` files are in `.gitignore`

```gitignore
.env
.env.local
.env.production
*.pem
*.key
```

4. **Minimum Length**: All secrets should be at least 32 characters for security

5. **Rotation**: Rotate secrets periodically (every 90 days recommended)

## JWT Token Security

The OAuth Plugin integrates with JWT Auth Plugin for authentication token generation.

### JWT Token Flow

1. User completes OAuth authentication
2. App's `onAuthSuccess` callback creates/links user account
3. App calls `ctx.plugins.jwtAuth.createToken(payload, roles)` to generate JWT
4. OAuth plugin returns JWT to client
5. Client uses JWT for subsequent authenticated requests

### JWT Security Requirements

**JWT Auth Plugin must be configured with:**

1. **Strong Secret**: Minimum 32 characters, cryptographically secure
2. **Appropriate Expiration**: Balance security vs user experience
3. **Secure Storage**: Clients must store JWT securely (httpOnly cookies or secure storage)

### Client-Side JWT Storage

**Recommended Approaches:**

1. **httpOnly Cookies** (Most Secure):

    - Immune to XSS attacks
    - Automatically sent with requests
    - Configure with `Secure` and `SameSite` flags

2. **Secure Storage (Mobile Apps)**:

    - iOS: Keychain
    - Android: Keystore
    - Never store in plain text

3. **localStorage/sessionStorage** (Use with caution):
    - Vulnerable to XSS attacks
    - Only use if XSS protection is comprehensive
    - Never store long-lived tokens

### Token Transmission

**Always use HTTPS when transmitting JWT tokens:**

```typescript
// Good - HTTPS with Authorization header
fetch("https://api.myapp.com/profile", {
    headers: {
        Authorization: `Bearer ${jwtToken}`,
    },
});

// Bad - HTTP exposes token
fetch("http://api.myapp.com/profile", {
    headers: {
        Authorization: `Bearer ${jwtToken}`,
    },
});
```

## Session Management

### OAuth Session Storage

-   **Storage**: MongoDB collection `oauth_sessions`
-   **TTL**: 10 minutes (configurable via `sessionTTL` option)
-   **Cleanup**: Automatic via MongoDB TTL index
-   **Purpose**: Temporary storage for OAuth state validation

### Session Security

1. **Short Lifespan**: 10-minute TTL prevents session table bloat and reduces attack window
2. **One-Time Use**: Sessions deleted after successful validation
3. **Indexed Cleanup**: MongoDB TTL index automatically removes expired sessions
4. **No Sensitive Data**: Sessions only store state, provider, and redirect URI

### TTL Index Configuration

```typescript
// Automatically created by plugin during init
await db.collection("oauth_sessions").createIndex(
    { createdAt: 1 },
    { expireAfterSeconds: 600 } // 10 minutes
);
```

## Input Validation

All handler inputs are validated before processing to prevent injection and abuse.

### Validated Inputs

1. **Provider Parameter**: Must be 'github' or 'google'
2. **State Parameter**: Required, validated against stored state
3. **Authorization Code**: Required for token exchange
4. **Response Type**: Must be 'json' if provided
5. **Redirect URI**: Must be valid HTTP/HTTPS URL

### Validation Examples

```typescript
// Provider validation
validateProvider(provider); // Throws if not 'github' or 'google'

// Response type validation
validateResponseType(responseType); // Throws if not 'json' or undefined

// Redirect URI validation
validateRedirectUri(redirectUri); // Throws if invalid URL format
```

### What This Prevents

-   Open redirect vulnerabilities
-   Invalid provider abuse
-   Malformed request exploitation
-   Parameter injection attacks

## Error Handling

### Error Message Security

The plugin provides user-friendly error messages that don't expose:

-   Internal system details
-   Database structure
-   OAuth client secrets
-   Token values
-   Stack traces (in production)

### Error Structure

```typescript
interface OAuthError {
    code: string; // Error code for programmatic handling
    message: string; // User-friendly message
    details?: any; // Internal details (logged, not shown to user)
}
```

### Error Codes

-   `invalid_state`: State parameter mismatch
-   `access_denied`: User denied authorization
-   `invalid_grant`: Authorization code expired
-   `network_error`: Provider unreachable
-   `jwt_generation_failed`: JWT creation failed
-   `invalid_request`: Invalid input parameters

### Error Logging

**Good Practice:**

```typescript
// Log with details for debugging (internal only)
console.error("OAuth error:", {
    code: error.code,
    message: error.message,
    details: error.details, // Contains technical details
});

// Return sanitized error to client
return {
    status: 400,
    data: {
        error: error.code,
        message: error.message, // User-friendly only
    },
};
```

**Bad Practice:**

```typescript
// Never expose internal details to clients
return {
    status: 500,
    data: {
        error: error.stack, // Exposes code structure
        secret: clientSecret, // Exposes credentials
        query: mongoQuery, // Exposes database structure
    },
};
```

## Security Checklist

### Configuration Security

-   [ ] HTTPS enabled for all callback URLs in production
-   [ ] All secrets stored in environment variables or secret management service
-   [ ] Secrets are at least 32 characters long
-   [ ] `.env` files in `.gitignore`
-   [ ] No secrets committed to version control

### OAuth Flow Security

-   [ ] State parameter validation enabled (default)
-   [ ] Session TTL configured appropriately (default 10 minutes)
-   [ ] MongoDB TTL index created (automatic)
-   [ ] Token encryption enabled if storing tokens (`storeTokens: true`)

### JWT Integration Security

-   [ ] JWT Auth Plugin installed and configured
-   [ ] JWT secret is strong (32+ characters)
-   [ ] JWT expiration configured appropriately
-   [ ] Clients store JWT securely (httpOnly cookies recommended)

### Application Security

-   [ ] Input validation enabled (automatic)
-   [ ] Error messages don't expose sensitive information (automatic)
-   [ ] CORS configured correctly for frontend domains
-   [ ] Rate limiting implemented for auth endpoints
-   [ ] Monitoring and alerting configured for auth failures

### Operational Security

-   [ ] Regular secret rotation schedule (90 days recommended)
-   [ ] Security audit logs enabled
-   [ ] Failed authentication attempts monitored
-   [ ] Database backups encrypted
-   [ ] Incident response plan documented

## Security Audit

Perform regular security audits using this checklist:

1. Review all OAuth callback URLs use HTTPS
2. Verify secrets are not in version control (`git grep -i secret`)
3. Check MongoDB TTL index is active (`db.oauth_sessions.getIndexes()`)
4. Test CSRF protection (attempt to use old state parameter)
5. Test token encryption (verify database tokens are encrypted)
6. Review error logs for sensitive information leakage
7. Test input validation (attempt invalid providers, response types)
8. Verify JWT tokens are transmitted over HTTPS only

## Reporting Security Issues

If you discover a security vulnerability in the OAuth Plugin:

1. **DO NOT** create a public GitHub issue
2. Email security concerns to: security@your-domain.com
3. Include detailed description and reproduction steps
4. Allow reasonable time for fix before public disclosure

## References

-   [OAuth 2.0 Security Best Practices](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics)
-   [OWASP Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html)
-   [Node.js Security Best Practices](https://nodejs.org/en/docs/guides/security/)
-   [MongoDB Security Checklist](https://docs.mongodb.com/manual/administration/security-checklist/)
