feat(phase-3): implement token endpoint and OAuth 2.0 flow
Phase 3 Implementation: - Token service with secure token generation and validation - Token endpoint (POST /token) with OAuth 2.0 compliance - Database migration 003 for tokens table - Authorization code validation and single-use enforcement Phase 1 Updates: - Enhanced CodeStore to support dict values with JSON serialization - Maintains backward compatibility Phase 2 Updates: - Authorization codes now include PKCE fields, used flag, timestamps - Complete metadata structure for token exchange Security: - 256-bit cryptographically secure tokens (secrets.token_urlsafe) - SHA-256 hashed storage (no plaintext) - Constant-time comparison for validation - Single-use code enforcement with replay detection Testing: - 226 tests passing (100%) - 87.27% coverage (exceeds 80% requirement) - OAuth 2.0 compliance verified This completes the v1.0.0 MVP with full IndieAuth authorization code flow. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,10 @@ class Config:
|
||||
TOKEN_EXPIRY: int
|
||||
CODE_EXPIRY: int
|
||||
|
||||
# Token Cleanup (Phase 3)
|
||||
TOKEN_CLEANUP_ENABLED: bool
|
||||
TOKEN_CLEANUP_INTERVAL: int
|
||||
|
||||
# Logging
|
||||
LOG_LEVEL: str
|
||||
DEBUG: bool
|
||||
@@ -82,6 +86,10 @@ class Config:
|
||||
cls.TOKEN_EXPIRY = int(os.getenv("GONDULF_TOKEN_EXPIRY", "3600"))
|
||||
cls.CODE_EXPIRY = int(os.getenv("GONDULF_CODE_EXPIRY", "600"))
|
||||
|
||||
# Token Cleanup Configuration
|
||||
cls.TOKEN_CLEANUP_ENABLED = os.getenv("GONDULF_TOKEN_CLEANUP_ENABLED", "false").lower() == "true"
|
||||
cls.TOKEN_CLEANUP_INTERVAL = int(os.getenv("GONDULF_TOKEN_CLEANUP_INTERVAL", "3600"))
|
||||
|
||||
# Logging
|
||||
cls.DEBUG = os.getenv("GONDULF_DEBUG", "false").lower() == "true"
|
||||
# If DEBUG is true, default LOG_LEVEL to DEBUG, otherwise INFO
|
||||
@@ -108,16 +116,26 @@ class Config:
|
||||
f"GONDULF_SMTP_PORT must be between 1 and 65535, got {cls.SMTP_PORT}"
|
||||
)
|
||||
|
||||
# Validate expiry times are positive
|
||||
if cls.TOKEN_EXPIRY <= 0:
|
||||
# Validate expiry times are positive and within bounds
|
||||
if cls.TOKEN_EXPIRY < 300: # Minimum 5 minutes
|
||||
raise ConfigurationError(
|
||||
f"GONDULF_TOKEN_EXPIRY must be positive, got {cls.TOKEN_EXPIRY}"
|
||||
"GONDULF_TOKEN_EXPIRY must be at least 300 seconds (5 minutes)"
|
||||
)
|
||||
if cls.TOKEN_EXPIRY > 86400: # Maximum 24 hours
|
||||
raise ConfigurationError(
|
||||
"GONDULF_TOKEN_EXPIRY must be at most 86400 seconds (24 hours)"
|
||||
)
|
||||
if cls.CODE_EXPIRY <= 0:
|
||||
raise ConfigurationError(
|
||||
f"GONDULF_CODE_EXPIRY must be positive, got {cls.CODE_EXPIRY}"
|
||||
)
|
||||
|
||||
# Validate cleanup interval if enabled
|
||||
if cls.TOKEN_CLEANUP_ENABLED and cls.TOKEN_CLEANUP_INTERVAL < 600:
|
||||
raise ConfigurationError(
|
||||
"GONDULF_TOKEN_CLEANUP_INTERVAL must be at least 600 seconds (10 minutes)"
|
||||
)
|
||||
|
||||
|
||||
# Configuration is loaded lazily or explicitly by the application
|
||||
# Tests should call Config.load() explicitly in fixtures
|
||||
|
||||
Reference in New Issue
Block a user