Skip to content

feat: Add JWT and API key authentication infrastructure#35

Merged
elmorem merged 1 commit intomainfrom
feat/authentication-and-authorization
Dec 11, 2025
Merged

feat: Add JWT and API key authentication infrastructure#35
elmorem merged 1 commit intomainfrom
feat/authentication-and-authorization

Conversation

@elmorem
Copy link
Copy Markdown
Owner

@elmorem elmorem commented Dec 11, 2025

Summary

  • Add comprehensive authentication and authorization framework
  • Implement JWT token authentication with PyJWT
  • Add API key authentication with secure hashing
  • Create permission-based authorization system
  • Provide FastAPI dependencies for easy integration

Implementation Details

Authentication Package (shared/auth/)

Core modules:

  • models.py - UserIdentity, Permission enum, TokenPayload, APIKeyInfo
  • jwt.py - JWT token creation, validation, and refresh
  • api_key.py - API key generation, hashing, and verification
  • dependencies.py - FastAPI dependencies for auth and authorization
  • config.py - Authentication settings (environment-based)

JWT Authentication (jwt.py:17-147)

Features:

  • Token creation with user claims (user_id, org_id, email, permissions)
  • HS256 signing algorithm (configurable)
  • Expiration validation
  • Token refresh capability
  • Issuer validation

Example:

jwt_handler = JWTHandler(secret_key="your-secret")
token = jwt_handler.create_access_token(
    user_id="user_123",
    permissions=[Permission.SESSION_CREATE, Permission.MEMORY_READ],
)
identity = jwt_handler.verify_token(token)

API Key Authentication (api_key.py:14-92)

Features:

  • Generate secure API keys (format: ck_xxxxx...)
  • SHA-256 key hashing for storage
  • Key expiration support
  • Rate limiting metadata
  • Active/inactive key status

Example:

api_key_handler = APIKeyHandler()
api_key = api_key_handler.generate_api_key()  # "ck_..."

key_info = APIKeyInfo(
    key_id="key_001",
    user_id="user_123",
    permissions=[Permission.MEMORY_READ],
    rate_limit=1000,
)
api_key_handler.register_api_key(api_key, key_info)

Permission System (models.py:18-44)

Permission types:

  • Session: CREATE, READ, UPDATE, DELETE, LIST
  • Memory: CREATE, READ, UPDATE, DELETE, SEARCH, LIST
  • Admin: READ, WRITE

Permission checking methods:

  • has_permission(perm) - Check single permission
  • has_any_permission([perms]) - Check if user has any
  • has_all_permissions([perms]) - Check if user has all

FastAPI Integration (dependencies.py:71-202)

Dependencies:

  • get_current_user - Require authentication (JWT or API key)
  • get_current_user_optional - Optional authentication
  • require_permissions(*perms) - Require specific permissions
  • require_any_permission(*perms) - Require any of the permissions

Example:

@app.post("/sessions")
async def create_session(
    user: Annotated[UserIdentity, Depends(require_permissions(Permission.SESSION_CREATE))],
):
    return {"user_id": user.user_id, "org_id": user.org_id}

User Identity Model (models.py:47-87)

Contains:

  • user_id - Unique user identifier
  • org_id - Organization identifier (optional)
  • email, name - User metadata
  • permissions - List of granted permissions
  • provider - Auth method used (JWT, API_KEY, SERVICE)
  • metadata - Additional context

Configuration (config.py:11-33)

Environment variables:

  • AUTH_JWT_SECRET_KEY - Required JWT signing secret
  • AUTH_JWT_ALGORITHM - JWT algorithm (default: HS256)
  • AUTH_JWT_ACCESS_TOKEN_EXPIRE_MINUTES - Token TTL (default: 60)
  • AUTH_API_KEY_ENABLED - Enable API keys (default: true)
  • AUTH_REQUIRE_AUTH - Global auth requirement (default: true)
  • AUTH_REQUIRE_AUTH_EXCEPTIONS - Endpoints exempt from auth

Client Authentication

JWT Bearer Token

curl -H "Authorization: Bearer eyJ0eXAi..." \
  http://localhost:8000/api/v1/sessions

API Key

curl -H "X-API-Key: ck_xxxxx..." \
  http://localhost:8000/api/v1/sessions

Integration Guide

1. Configure Handlers

from shared.auth.jwt import JWTHandler
from shared.auth.api_key import APIKeyHandler
from shared.auth.config import AuthSettings

auth_settings = AuthSettings()
jwt_handler = JWTHandler(secret_key=auth_settings.jwt_secret_key)
api_key_handler = APIKeyHandler()

2. Override Dependencies

from shared.auth.dependencies import get_jwt_handler, get_api_key_handler

app.dependency_overrides[get_jwt_handler] = lambda: jwt_handler
app.dependency_overrides[get_api_key_handler] = lambda: api_key_handler

3. Protect Endpoints

from shared.auth.dependencies import get_current_user, require_permissions

@app.get("/protected")
async def protected(user: Annotated[UserIdentity, Depends(get_current_user)]):
    return {"user": user.user_id}

Security Features

  • ✅ JWT signature validation
  • ✅ Token expiration checking
  • ✅ API key SHA-256 hashing
  • ✅ Permission-based access control
  • ✅ Rate limiting metadata support
  • ✅ Key expiration support
  • ✅ Secure key generation (32 bytes entropy)
  • ✅ Proper exception chaining

Error Responses

  • 401 Unauthorized - Missing or invalid credentials
  • 403 Forbidden - Valid auth but insufficient permissions

Documentation

Comprehensive usage guide in shared/auth/README.md with:

  • Quick start examples
  • Configuration options
  • Permission types
  • Security best practices
  • Client authentication examples

Future Enhancements

This PR provides the foundation. Future work can add:

  • Auth middleware for automatic enforcement
  • Token blacklist for logout
  • Refresh token rotation
  • OAuth2 provider integration
  • User management endpoints
  • Permission management API

Test Plan

  • Type checks pass (mypy - JWT import warnings expected)
  • Code formatting applied (black)
  • Manual testing of JWT token creation and validation
  • Manual testing of API key generation and verification
  • Test permission checking methods
  • Test FastAPI dependency integration
  • Test with actual services

🤖 Generated with Claude Code

Implement comprehensive authentication and authorization framework with JWT tokens and API keys, permission-based access control, and FastAPI integration.

Changes:
- Create shared/auth package with authentication utilities
- Add JWT token encoding, decoding, and validation with PyJWT
- Add API key generation, hashing, and validation
- Create Permission enum for fine-grained access control
- Add UserIdentity model for authenticated user context
- Create FastAPI dependencies for authentication and authorization
- Add require_permissions() and require_any_permission() decorators

Authentication Methods:
- JWT Bearer tokens (Authorization: Bearer <token>)
- API keys (X-API-Key: ck_xxxxx...)
- Service-to-service authentication support

Permission System:
- Session permissions (CREATE, READ, UPDATE, DELETE, LIST)
- Memory permissions (CREATE, READ, UPDATE, DELETE, SEARCH, LIST)
- Admin permissions (READ, WRITE)

Key Features:
- Dual authentication support (JWT + API keys)
- Permission-based authorization with has_permission(), has_any_permission(), has_all_permissions()
- FastAPI dependency injection for auth
- Token expiration and validation
- API key expiration and rate limiting
- Configurable auth settings via environment variables
- Comprehensive error handling (401 Unauthorized, 403 Forbidden)

Usage Example:
```python
from shared.auth.dependencies import get_current_user, require_permissions
from shared.auth.models import Permission

@app.post("/sessions")
async def create_session(
    user: Annotated[UserIdentity, Depends(require_permissions(Permission.SESSION_CREATE))],
):
    return {"user_id": user.user_id}
```

Configuration:
- AUTH_JWT_SECRET_KEY: JWT signing key
- AUTH_JWT_ALGORITHM: JWT algorithm (default: HS256)
- AUTH_JWT_ACCESS_TOKEN_EXPIRE_MINUTES: Token TTL (default: 60)
- AUTH_API_KEY_ENABLED: Enable API keys (default: true)
- AUTH_REQUIRE_AUTH: Require auth globally (default: true)

Documentation: See shared/auth/README.md for detailed usage guide

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@elmorem elmorem merged commit ee87f0f into main Dec 11, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant