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>
428 lines
21 KiB
Markdown
428 lines
21 KiB
Markdown
# StarPunk Simplified Authentication Architecture
|
|
|
|
## Overview
|
|
|
|
After removing the custom IndieAuth authorization server, StarPunk becomes a pure Micropub server that relies on external providers for all authentication and authorization.
|
|
|
|
## Architecture Diagrams
|
|
|
|
### Before: Complex Mixed-Mode Architecture
|
|
```
|
|
┌──────────────────────────────────────────────────────────────┐
|
|
│ StarPunk Instance │
|
|
│ │
|
|
│ ┌────────────────────────────────────────────────────────┐ │
|
|
│ │ Web Interface │ │
|
|
│ │ ┌─────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
|
|
│ │ │ Admin Login │ │ Authorization │ │ Token Issuer │ │ │
|
|
│ │ └─────────────┘ └──────────────┘ └──────────────┘ │ │
|
|
│ └────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌────────────────────────────────────────────────────────┐ │
|
|
│ │ Auth Module │ │
|
|
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
|
|
│ │ │ Sessions │ │ PKCE │ │ Tokens │ │ Codes │ │ │
|
|
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
|
|
│ └────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌────────────────────────────────────────────────────────┐ │
|
|
│ │ Database │ │
|
|
│ │ ┌────────┐ ┌──────────────────┐ ┌─────────────────┐ │ │
|
|
│ │ │ Users │ │ authorization_codes│ │ tokens │ │ │
|
|
│ │ └────────┘ └──────────────────┘ └─────────────────┘ │ │
|
|
│ └────────────────────────────────────────────────────────┘ │
|
|
└──────────────────────────────────────────────────────────────┘
|
|
|
|
Problems:
|
|
- 500+ lines of security-critical code
|
|
- Dual role: authorization server AND resource server
|
|
- Complex token lifecycle management
|
|
- Database bloat with token storage
|
|
- Maintenance burden for security updates
|
|
```
|
|
|
|
### After: Clean Separation of Concerns
|
|
```
|
|
┌──────────────────────────────────────────────────────────────┐
|
|
│ StarPunk Instance │
|
|
│ │
|
|
│ ┌────────────────────────────────────────────────────────┐ │
|
|
│ │ Web Interface │ │
|
|
│ │ ┌─────────────┐ ┌──────────────┐ │ │
|
|
│ │ │ Admin Login │ │ Micropub │ │ │
|
|
│ │ └─────────────┘ └──────────────┘ │ │
|
|
│ └────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌────────────────────────────────────────────────────────┐ │
|
|
│ │ Auth Module │ │
|
|
│ │ ┌──────────────┐ ┌──────────────────────┐ │ │
|
|
│ │ │ Sessions │ │ Token Verification │ │ │
|
|
│ │ │ (Admin Only) │ │ (External Provider) │ │ │
|
|
│ │ └──────────────┘ └──────────────────────┘ │ │
|
|
│ └────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌────────────────────────────────────────────────────────┐ │
|
|
│ │ Database │ │
|
|
│ │ ┌────────┐ ┌──────────┐ ┌─────────┐ │ │
|
|
│ │ │ Users │ │auth_state│ │ posts │ (No token tables)│ │
|
|
│ │ └────────┘ └──────────┘ └─────────┘ │ │
|
|
│ └────────────────────────────────────────────────────────┘ │
|
|
└──────────────────────────────────────────────────────────────┘
|
|
│
|
|
│ API Calls
|
|
▼
|
|
┌──────────────────────────────────────────────────────────────┐
|
|
│ External IndieAuth Providers │
|
|
│ ┌─────────────────────┐ ┌─────────────────────────┐ │
|
|
│ │ indieauth.com │ │ tokens.indieauth.com │ │
|
|
│ │ (Authorization) │ │ (Token Verification) │ │
|
|
│ └─────────────────────┘ └─────────────────────────┘ │
|
|
└──────────────────────────────────────────────────────────────┘
|
|
|
|
Benefits:
|
|
- 500+ lines of code removed
|
|
- Clear single responsibility
|
|
- No security burden
|
|
- Minimal database footprint
|
|
- Zero maintenance for auth code
|
|
```
|
|
|
|
## Authentication Flows
|
|
|
|
### Flow 1: Admin Authentication (Unchanged)
|
|
```
|
|
Admin User StarPunk IndieLogin.com
|
|
│ │ │
|
|
├──── GET /admin/login ───→ │ │
|
|
│ │ │
|
|
│ ←── Login Form ─────────── │ │
|
|
│ │ │
|
|
├──── POST /auth/login ───→ │ │
|
|
│ (me=admin.com) │ │
|
|
│ ├──── Redirect ──────────────→ │
|
|
│ │ (client_id=starpunk.com) │
|
|
│ ←──────────── Authorization Request ───────────────────── │
|
|
│ │ │
|
|
├───────────── Authenticate with IndieLogin ──────────────→ │
|
|
│ │ │
|
|
│ │ ←── Callback ────────────────│
|
|
│ │ (me=admin.com) │
|
|
│ │ │
|
|
│ ←── Session Cookie ─────── │ │
|
|
│ │ │
|
|
│ Admin Access │ │
|
|
```
|
|
|
|
### Flow 2: Micropub Client Authentication (Simplified)
|
|
```
|
|
Micropub Client StarPunk External Token Endpoint
|
|
│ │ │
|
|
├─── POST /micropub ───→ │ │
|
|
│ Bearer: token123 │ │
|
|
│ ├──── GET /token ─────────→ │
|
|
│ │ Bearer: token123 │
|
|
│ │ │
|
|
│ │ ←── Token Info ──────────│
|
|
│ │ {me, scope, client_id} │
|
|
│ │ │
|
|
│ │ [Validate me==ADMIN_ME] │
|
|
│ │ [Check scope includes │
|
|
│ │ "create"] │
|
|
│ │ │
|
|
│ ←── 201 Created ────────│ │
|
|
│ Location: /post/123 │ │
|
|
```
|
|
|
|
## Component Responsibilities
|
|
|
|
### StarPunk Components
|
|
|
|
#### 1. Admin Authentication (`/auth/*`)
|
|
**Responsibility**: Manage admin sessions via IndieLogin.com
|
|
**Does**:
|
|
- Initiate OAuth flow with IndieLogin.com
|
|
- Validate callback and create session
|
|
- Manage session lifecycle
|
|
|
|
**Does NOT**:
|
|
- Issue tokens
|
|
- Store passwords
|
|
- Manage user identities
|
|
|
|
#### 2. Micropub Endpoint (`/micropub`)
|
|
**Responsibility**: Accept and process Micropub requests
|
|
**Does**:
|
|
- Extract Bearer tokens from requests
|
|
- Verify tokens with external endpoint
|
|
- Create/update/delete posts
|
|
- Return proper Micropub responses
|
|
|
|
**Does NOT**:
|
|
- Issue tokens
|
|
- Manage authorization codes
|
|
- Store token data
|
|
|
|
#### 3. Token Verification Module
|
|
**Responsibility**: Validate tokens with external providers
|
|
**Does**:
|
|
- Call external token endpoint
|
|
- Cache valid tokens (5 min TTL)
|
|
- Validate scope and identity
|
|
|
|
**Does NOT**:
|
|
- Generate tokens
|
|
- Store tokens permanently
|
|
- Manage token lifecycle
|
|
|
|
### External Provider Responsibilities
|
|
|
|
#### indieauth.com
|
|
- User authentication
|
|
- Authorization consent
|
|
- Authorization code generation
|
|
- Profile discovery
|
|
|
|
#### tokens.indieauth.com
|
|
- Token issuance
|
|
- Token verification
|
|
- Token revocation
|
|
- Scope management
|
|
|
|
## Configuration
|
|
|
|
### Required Settings
|
|
```ini
|
|
# Identity of the admin user
|
|
ADMIN_ME=https://your-domain.com
|
|
|
|
# External token endpoint for verification
|
|
TOKEN_ENDPOINT=https://tokens.indieauth.com/token
|
|
|
|
# Admin session secret (existing)
|
|
SECRET_KEY=your-secret-key
|
|
```
|
|
|
|
### HTML Discovery
|
|
```html
|
|
<!-- Added to all pages -->
|
|
<link rel="authorization_endpoint" href="https://indieauth.com/auth">
|
|
<link rel="token_endpoint" href="https://tokens.indieauth.com/token">
|
|
<link rel="micropub" href="https://starpunk.example.com/micropub">
|
|
```
|
|
|
|
## Security Model
|
|
|
|
### Trust Boundaries
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Trusted Zone │
|
|
│ ┌──────────────────────────────────────────────────────┐ │
|
|
│ │ StarPunk Application │ │
|
|
│ │ - Session management │ │
|
|
│ │ - Post creation/management │ │
|
|
│ │ - Admin interface │ │
|
|
│ └──────────────────────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
│
|
|
Token Verification API
|
|
│
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Semi-Trusted Zone │
|
|
│ ┌──────────────────────────────────────────────────────┐ │
|
|
│ │ External IndieAuth Providers │ │
|
|
│ │ - Token validation │ │
|
|
│ │ - Identity verification │ │
|
|
│ └──────────────────────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
│
|
|
User Authentication
|
|
│
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Untrusted Zone │
|
|
│ ┌──────────────────────────────────────────────────────┐ │
|
|
│ │ Micropub Clients │ │
|
|
│ │ - Must provide valid Bearer tokens │ │
|
|
│ │ - Tokens verified on every request │ │
|
|
│ └──────────────────────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Security Benefits of Simplified Architecture
|
|
|
|
1. **Reduced Attack Surface**
|
|
- No token generation = no cryptographic mistakes
|
|
- No token storage = no database leaks
|
|
- No PKCE = no implementation errors
|
|
|
|
2. **Specialized Security**
|
|
- Auth providers focus solely on security
|
|
- Regular updates from specialized teams
|
|
- Community-vetted implementations
|
|
|
|
3. **Clear Boundaries**
|
|
- StarPunk only verifies, never issues
|
|
- Single source of truth (external provider)
|
|
- No confused deputy problems
|
|
|
|
## Performance Characteristics
|
|
|
|
### Token Verification Performance
|
|
```
|
|
Without Cache:
|
|
┌──────────┐ 200-500ms ┌─────────────┐
|
|
│ Micropub ├───────────────────→│Token Endpoint│
|
|
└──────────┘ └─────────────┘
|
|
|
|
With Cache (95% hit rate):
|
|
┌──────────┐ <1ms ┌─────────────┐
|
|
│ Micropub ├───────────────────→│ Memory Cache │
|
|
└──────────┘ └─────────────┘
|
|
```
|
|
|
|
### Cache Strategy
|
|
```python
|
|
Cache Key: SHA256(token)
|
|
Cache Value: {
|
|
'me': 'https://user.com',
|
|
'client_id': 'https://client.com',
|
|
'scope': 'create update delete',
|
|
'expires_at': timestamp + 300 # 5 minutes
|
|
}
|
|
```
|
|
|
|
### Expected Latencies
|
|
- First request: 200-500ms (external API)
|
|
- Cached request: <1ms
|
|
- Admin login: 1-2s (OAuth flow)
|
|
- Post creation: <50ms (after auth)
|
|
|
|
## Migration Impact
|
|
|
|
### Breaking Changes
|
|
1. **All existing tokens invalid**
|
|
- Users must re-authenticate
|
|
- No migration path for tokens
|
|
|
|
2. **Endpoint removal**
|
|
- `/auth/authorization` → 404
|
|
- `/auth/token` → 404
|
|
|
|
3. **Configuration required**
|
|
- Must set `ADMIN_ME`
|
|
- Must configure domain with IndieAuth links
|
|
|
|
### Non-Breaking Preserved Functionality
|
|
1. **Admin login unchanged**
|
|
- Same URL (`/admin/login`)
|
|
- Same provider (IndieLogin.com)
|
|
- Sessions preserved
|
|
|
|
2. **Micropub API unchanged**
|
|
- Same endpoint (`/micropub`)
|
|
- Same request format
|
|
- Same response format
|
|
|
|
## Comparison with Other Systems
|
|
|
|
### WordPress + IndieAuth Plugin
|
|
- **Similarity**: External provider for auth
|
|
- **Difference**: WP has user management, we don't
|
|
|
|
### Known IndieWeb Sites
|
|
- **micro.blog**: Custom auth server (complex)
|
|
- **Indigenous**: Client only, uses external auth
|
|
- **StarPunk**: Micropub server only (simple)
|
|
|
|
### Architecture Philosophy
|
|
```
|
|
"Do one thing well"
|
|
│
|
|
├── StarPunk: Publish notes
|
|
├── IndieAuth.com: Authenticate users
|
|
└── Tokens.indieauth.com: Manage tokens
|
|
```
|
|
|
|
## Future Considerations
|
|
|
|
### Potential V2 Enhancements (NOT for V1)
|
|
1. **Multi-user support**
|
|
- Would require user management
|
|
- Still use external auth
|
|
|
|
2. **Multiple token endpoints**
|
|
- Support different providers per user
|
|
- Endpoint discovery from user domain
|
|
|
|
3. **Token caching layer**
|
|
- Redis for distributed caching
|
|
- Longer TTL with refresh
|
|
|
|
### Explicitly NOT Implementing
|
|
1. **Custom authorization server**
|
|
- Violates simplicity principle
|
|
- Maintenance burden
|
|
|
|
2. **Password authentication**
|
|
- Not IndieWeb compliant
|
|
- Security burden
|
|
|
|
3. **JWT validation**
|
|
- Not part of IndieAuth spec
|
|
- Unnecessary complexity
|
|
|
|
## Testing Strategy
|
|
|
|
### Unit Tests
|
|
```python
|
|
# Test external verification
|
|
@patch('httpx.get')
|
|
def test_token_verification(mock_get):
|
|
# Mock successful response
|
|
mock_get.return_value.status_code = 200
|
|
mock_get.return_value.json.return_value = {
|
|
'me': 'https://example.com',
|
|
'scope': 'create'
|
|
}
|
|
|
|
result = verify_token('test-token')
|
|
assert result is not None
|
|
```
|
|
|
|
### Integration Tests
|
|
```python
|
|
# Test with real endpoint (in CI)
|
|
def test_real_token_verification():
|
|
# Use test token from tokens.indieauth.com
|
|
token = get_test_token()
|
|
result = verify_token(token)
|
|
assert result['me'] == TEST_USER
|
|
```
|
|
|
|
### Manual Testing
|
|
1. Configure domain with IndieAuth links
|
|
2. Use Quill or Indigenous
|
|
3. Create test post
|
|
4. Verify token caching
|
|
|
|
## Metrics for Success
|
|
|
|
### Quantitative Metrics
|
|
- **Code removed**: >500 lines
|
|
- **Database tables removed**: 2
|
|
- **Complexity reduction**: ~40%
|
|
- **Test coverage maintained**: >90%
|
|
- **Performance**: <500ms token verification
|
|
|
|
### Qualitative Metrics
|
|
- **Clarity**: Clear separation of concerns
|
|
- **Maintainability**: No auth code to maintain
|
|
- **Security**: Specialized providers
|
|
- **Flexibility**: User choice of providers
|
|
- **Simplicity**: Focus on core functionality
|
|
|
|
---
|
|
|
|
**Document Version**: 1.0
|
|
**Created**: 2025-11-24
|
|
**Author**: StarPunk Architecture Team
|
|
**Purpose**: Document simplified authentication architecture after IndieAuth server removal |