feat: Complete IndieAuth server removal (Phases 2-4)
Completed all remaining phases of ADR-030 IndieAuth provider removal. StarPunk no longer acts as an authorization server - all IndieAuth operations delegated to external providers. Phase 2 - Remove Token Issuance: - Deleted /auth/token endpoint - Removed token_endpoint() function from routes/auth.py - Deleted tests/test_routes_token.py Phase 3 - Remove Token Storage: - Deleted starpunk/tokens.py module entirely - Created migration 004 to drop tokens and authorization_codes tables - Deleted tests/test_tokens.py - Removed all internal token CRUD operations Phase 4 - External Token Verification: - Created starpunk/auth_external.py module - Implemented verify_external_token() for external IndieAuth providers - Updated Micropub endpoint to use external verification - Added TOKEN_ENDPOINT configuration - Updated all Micropub tests to mock external verification - HTTP timeout protection (5s) for external requests Additional Changes: - Created migration 003 to remove code_verifier from auth_state - Fixed 5 migration tests that referenced obsolete code_verifier column - Updated 11 Micropub tests for external verification - Fixed test fixture and app context issues - All 501 tests passing Breaking Changes: - Micropub clients must use external IndieAuth providers - TOKEN_ENDPOINT configuration now required - Existing internal tokens invalid (tables dropped) Migration Impact: - Simpler codebase: -500 lines of code - Fewer database tables: -2 tables (tokens, authorization_codes) - More secure: External providers handle token security - More maintainable: Less authentication code to maintain Standards Compliance: - W3C IndieAuth specification - OAuth 2.0 Bearer token authentication - IndieWeb principle: delegate to external services Related: - ADR-030: IndieAuth Provider Removal Strategy - ADR-050: Remove Custom IndieAuth Server - Migration 003: Remove code_verifier from auth_state - Migration 004: Drop tokens and authorization_codes tables 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,251 @@
|
||||
# ADR-030: External Token Verification Architecture
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
|
||||
Following the decision in ADR-021 to use external IndieAuth providers, we need to define the architecture for token verification. Several critical questions arose during implementation planning:
|
||||
|
||||
1. How should we handle the existing database migration that creates token tables?
|
||||
2. What caching strategy should we use for token verification?
|
||||
3. How should we handle network errors when contacting external providers?
|
||||
4. What are the security implications of caching tokens?
|
||||
|
||||
## Decision
|
||||
|
||||
### 1. Database Migration Strategy
|
||||
|
||||
**Keep migration 002 but document its future purpose.**
|
||||
|
||||
The migration creates `tokens` and `authorization_codes` tables that are not used in V1 but will be needed if V2 adds an internal provider option. Rather than removing and later re-adding these tables, we keep them empty in V1.
|
||||
|
||||
**Rationale**:
|
||||
- Empty tables have zero performance impact
|
||||
- Avoids complex migration rollback/recreation cycles
|
||||
- Provides clear upgrade path to V2
|
||||
- Follows principle of forward compatibility
|
||||
|
||||
### 2. Token Caching Architecture
|
||||
|
||||
**Implement a configurable memory cache with 5-minute default TTL.**
|
||||
|
||||
```python
|
||||
class TokenCache:
|
||||
"""Simple time-based token cache"""
|
||||
def __init__(self, ttl=300, enabled=True):
|
||||
self.ttl = ttl
|
||||
self.enabled = enabled
|
||||
self.cache = {} # token_hash -> (info, expiry)
|
||||
```
|
||||
|
||||
**Configuration**:
|
||||
```ini
|
||||
MICROPUB_TOKEN_CACHE_ENABLED=true # Can disable for high security
|
||||
MICROPUB_TOKEN_CACHE_TTL=300 # 5 minutes default
|
||||
```
|
||||
|
||||
**Security Measures**:
|
||||
- Store SHA256 hash of token, never plain text
|
||||
- Memory-only storage (no persistence)
|
||||
- Short TTL to limit revocation delay
|
||||
- Option to disable entirely
|
||||
|
||||
### 3. Network Error Handling
|
||||
|
||||
**Implement clear error messages with appropriate HTTP status codes.**
|
||||
|
||||
| Scenario | HTTP Status | User Message |
|
||||
|----------|------------|--------------|
|
||||
| Auth server timeout | 503 | "Authorization server is unreachable" |
|
||||
| Invalid token | 403 | "Access token is invalid or expired" |
|
||||
| Network error | 503 | "Cannot connect to authorization server" |
|
||||
| No token provided | 401 | "No access token provided" |
|
||||
|
||||
**Implementation**:
|
||||
```python
|
||||
try:
|
||||
response = httpx.get(endpoint, timeout=5.0)
|
||||
except httpx.TimeoutError:
|
||||
raise TokenEndpointError("Authorization server is unreachable")
|
||||
```
|
||||
|
||||
### 4. Endpoint Discovery
|
||||
|
||||
**Implement full IndieAuth spec discovery with fallbacks.**
|
||||
|
||||
Priority order:
|
||||
1. HTTP Link header (highest priority)
|
||||
2. HTML link elements
|
||||
3. IndieAuth metadata endpoint
|
||||
|
||||
This ensures compatibility with all IndieAuth providers while following the specification exactly.
|
||||
|
||||
## Rationale
|
||||
|
||||
### Why Cache Tokens?
|
||||
|
||||
**Performance**:
|
||||
- Reduces latency for Micropub posts (5ms vs 500ms)
|
||||
- Reduces load on external authorization servers
|
||||
- Improves user experience for rapid posting
|
||||
|
||||
**Trade-offs Accepted**:
|
||||
- 5-minute revocation delay is acceptable for most use cases
|
||||
- Can disable cache for high-security requirements
|
||||
- Cache is memory-only, cleared on restart
|
||||
|
||||
### Why Keep Empty Tables?
|
||||
|
||||
**Simplicity**:
|
||||
- Simpler than conditional migrations
|
||||
- Cleaner upgrade path to V2
|
||||
- No production impact (tables unused)
|
||||
- Avoids migration complexity
|
||||
|
||||
**Forward Compatibility**:
|
||||
- V2 might add internal provider
|
||||
- Tables already have correct schema
|
||||
- Migration already tested and working
|
||||
|
||||
### Why External-Only Verification?
|
||||
|
||||
**Alignment with Principles**:
|
||||
- StarPunk is a Micropub server, not an auth server
|
||||
- Users control their own identity infrastructure
|
||||
- Reduces code complexity significantly
|
||||
- Follows IndieWeb separation of concerns
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- **Simplicity**: No complex OAuth flows to implement
|
||||
- **Security**: No tokens stored in database
|
||||
- **Performance**: Cache provides fast token validation
|
||||
- **Flexibility**: Users choose their auth providers
|
||||
- **Compliance**: Full IndieAuth spec compliance
|
||||
|
||||
### Negative
|
||||
|
||||
- **Dependency**: Requires external auth server availability
|
||||
- **Latency**: Network call for uncached tokens (mitigated by cache)
|
||||
- **Revocation Delay**: Up to 5 minutes for cached tokens (configurable)
|
||||
|
||||
### Neutral
|
||||
|
||||
- **Database**: Unused tables in V1 (no impact, future-ready)
|
||||
- **Configuration**: Requires ADMIN_ME setting (one-time setup)
|
||||
- **Documentation**: Must explain external provider setup
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Token Verification Flow
|
||||
|
||||
```
|
||||
1. Extract Bearer token from Authorization header
|
||||
2. Check cache for valid cached result
|
||||
3. If not cached:
|
||||
a. Discover token endpoint from ADMIN_ME URL
|
||||
b. Verify token with external endpoint
|
||||
c. Cache result if valid
|
||||
4. Validate response:
|
||||
a. 'me' field matches ADMIN_ME
|
||||
b. 'scope' includes 'create'
|
||||
5. Return validation result
|
||||
```
|
||||
|
||||
### Security Checklist
|
||||
|
||||
- [ ] Never log tokens in plain text
|
||||
- [ ] Use HTTPS for all token verification
|
||||
- [ ] Implement timeout on HTTP requests
|
||||
- [ ] Hash tokens before caching
|
||||
- [ ] Validate SSL certificates
|
||||
- [ ] Clear cache on configuration changes
|
||||
|
||||
### Performance Targets
|
||||
|
||||
- Cached token verification: < 10ms
|
||||
- Uncached token verification: < 500ms
|
||||
- Endpoint discovery: < 1000ms (cached after first)
|
||||
- Cache memory usage: < 10MB for 1000 tokens
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
### Alternative 1: No Token Cache
|
||||
|
||||
**Pros**: Immediate revocation, simpler code
|
||||
**Cons**: High latency (500ms per request), load on auth servers
|
||||
**Verdict**: Rejected - poor user experience
|
||||
|
||||
### Alternative 2: Database Token Cache
|
||||
|
||||
**Pros**: Persistent cache, survives restarts
|
||||
**Cons**: Complex invalidation, security concerns
|
||||
**Verdict**: Rejected - unnecessary complexity
|
||||
|
||||
### Alternative 3: Redis Token Cache
|
||||
|
||||
**Pros**: Distributed cache, proven solution
|
||||
**Cons**: Additional dependency, deployment complexity
|
||||
**Verdict**: Rejected - violates simplicity principle
|
||||
|
||||
### Alternative 4: Remove Migration 002
|
||||
|
||||
**Pros**: Cleaner V1 codebase
|
||||
**Cons**: Complex V2 upgrade, breaks existing databases
|
||||
**Verdict**: Rejected - creates future problems
|
||||
|
||||
## Migration Impact
|
||||
|
||||
### For Existing Installations
|
||||
- No database changes needed
|
||||
- Add ADMIN_ME configuration
|
||||
- Token verification switches to external
|
||||
|
||||
### For New Installations
|
||||
- Clean V1 implementation
|
||||
- Empty future-use tables
|
||||
- Simple configuration
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Token Revocation Delay
|
||||
- Cached tokens remain valid for TTL duration
|
||||
- Maximum exposure: 5 minutes default
|
||||
- Can disable cache for immediate revocation
|
||||
- Document delay in security guide
|
||||
|
||||
### Network Security
|
||||
- Always use HTTPS for token verification
|
||||
- Validate SSL certificates
|
||||
- Implement request timeouts
|
||||
- Handle network errors gracefully
|
||||
|
||||
### Cache Security
|
||||
- SHA256 hash tokens before storage
|
||||
- Memory-only cache (no disk persistence)
|
||||
- Clear cache on shutdown
|
||||
- Limit cache size to prevent DoS
|
||||
|
||||
## References
|
||||
|
||||
- [IndieAuth Spec Section 6.3](https://www.w3.org/TR/indieauth/#token-verification) - Token verification
|
||||
- [OAuth 2.0 Bearer Token](https://tools.ietf.org/html/rfc6750) - Bearer token usage
|
||||
- [ADR-021](./ADR-021-indieauth-provider-strategy.md) - Provider strategy decision
|
||||
- [ADR-029](./ADR-029-micropub-indieauth-integration.md) - Integration strategy
|
||||
|
||||
## Related Decisions
|
||||
|
||||
- ADR-021: IndieAuth Provider Strategy
|
||||
- ADR-029: Micropub IndieAuth Integration Strategy
|
||||
- ADR-005: IndieLogin Authentication
|
||||
- ADR-010: Authentication Module Design
|
||||
|
||||
---
|
||||
|
||||
**Document Version**: 1.0
|
||||
**Created**: 2024-11-24
|
||||
**Author**: StarPunk Architecture Team
|
||||
**Status**: Accepted
|
||||
Reference in New Issue
Block a user