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>
593 lines
15 KiB
Markdown
593 lines
15 KiB
Markdown
# IndieAuth Removal: Phased Implementation Guide
|
|
|
|
## Overview
|
|
|
|
This document breaks down the IndieAuth server removal into testable phases, each with clear acceptance criteria and verification steps.
|
|
|
|
## Phase 1: Remove Authorization Server (4 hours)
|
|
|
|
### Objective
|
|
Remove the authorization endpoint and consent UI while keeping the system functional.
|
|
|
|
### Tasks
|
|
|
|
#### 1.1 Remove Authorization UI (30 min)
|
|
```bash
|
|
# Delete consent template
|
|
rm /home/phil/Projects/starpunk/templates/auth/authorize.html
|
|
|
|
# Verify
|
|
ls /home/phil/Projects/starpunk/templates/auth/
|
|
# Should be empty or not exist
|
|
```
|
|
|
|
#### 1.2 Remove Authorization Endpoint (1 hour)
|
|
In `/home/phil/Projects/starpunk/starpunk/routes/auth.py`:
|
|
- Delete `authorization_endpoint()` function
|
|
- Delete related imports from `starpunk.tokens`
|
|
- Keep admin auth routes intact
|
|
|
|
#### 1.3 Remove Authorization Tests (30 min)
|
|
```bash
|
|
# Delete test files
|
|
rm /home/phil/Projects/starpunk/tests/test_routes_authorization.py
|
|
rm /home/phil/Projects/starpunk/tests/test_auth_pkce.py
|
|
```
|
|
|
|
#### 1.4 Remove PKCE Implementation (1 hour)
|
|
From `/home/phil/Projects/starpunk/starpunk/auth.py`:
|
|
- Remove `generate_code_verifier()`
|
|
- Remove `calculate_code_challenge()`
|
|
- Remove PKCE validation logic
|
|
- Keep session management functions
|
|
|
|
#### 1.5 Update Route Registration (30 min)
|
|
Ensure no references to `/auth/authorization` in:
|
|
- URL route definitions
|
|
- Template URL generation
|
|
- Documentation
|
|
|
|
### Acceptance Criteria
|
|
|
|
✅ **Server Starts Successfully**
|
|
```bash
|
|
uv run python -m starpunk
|
|
# No import errors or missing route errors
|
|
```
|
|
|
|
✅ **Admin Login Works**
|
|
```bash
|
|
# Navigate to /admin/login
|
|
# Can still authenticate via IndieLogin.com
|
|
# Session created successfully
|
|
```
|
|
|
|
✅ **No Authorization Endpoint**
|
|
```bash
|
|
curl -I http://localhost:5000/auth/authorization
|
|
# Should return 404 Not Found
|
|
```
|
|
|
|
✅ **Tests Pass (Remaining)**
|
|
```bash
|
|
uv run pytest tests/ -k "not authorization and not pkce"
|
|
# All remaining tests pass
|
|
```
|
|
|
|
### Verification Commands
|
|
```bash
|
|
# Check for orphaned imports
|
|
grep -r "authorization_endpoint" /home/phil/Projects/starpunk/
|
|
# Should return nothing
|
|
|
|
# Check for PKCE references
|
|
grep -r "code_challenge\|code_verifier" /home/phil/Projects/starpunk/
|
|
# Should only appear in migration files or comments
|
|
```
|
|
|
|
---
|
|
|
|
## Phase 2: Remove Token Issuance (3 hours)
|
|
|
|
### Objective
|
|
Remove token generation and issuance while keeping token verification temporarily.
|
|
|
|
### Tasks
|
|
|
|
#### 2.1 Remove Token Endpoint (1 hour)
|
|
In `/home/phil/Projects/starpunk/starpunk/routes/auth.py`:
|
|
- Delete `token_endpoint()` function
|
|
- Remove token-related imports
|
|
|
|
#### 2.2 Remove Token Generation (1 hour)
|
|
In `/home/phil/Projects/starpunk/starpunk/tokens.py`:
|
|
- Remove `create_access_token()`
|
|
- Remove `create_authorization_code()`
|
|
- Remove `exchange_authorization_code()`
|
|
- Keep `verify_token()` temporarily (will modify in Phase 4)
|
|
|
|
#### 2.3 Remove Token Tests (30 min)
|
|
```bash
|
|
rm /home/phil/Projects/starpunk/tests/test_routes_token.py
|
|
rm /home/phil/Projects/starpunk/tests/test_tokens.py
|
|
```
|
|
|
|
#### 2.4 Clean Up Exceptions (30 min)
|
|
Remove custom exceptions:
|
|
- `InvalidAuthorizationCodeError`
|
|
- `ExpiredAuthorizationCodeError`
|
|
- Update error handling to use generic exceptions
|
|
|
|
### Acceptance Criteria
|
|
|
|
✅ **No Token Endpoint**
|
|
```bash
|
|
curl -I http://localhost:5000/auth/token
|
|
# Should return 404 Not Found
|
|
```
|
|
|
|
✅ **No Token Generation Code**
|
|
```bash
|
|
grep -r "create_access_token\|create_authorization_code" /home/phil/Projects/starpunk/starpunk/
|
|
# Should return nothing (except in comments)
|
|
```
|
|
|
|
✅ **Server Still Runs**
|
|
```bash
|
|
uv run python -m starpunk
|
|
# No import errors
|
|
```
|
|
|
|
✅ **Micropub Temporarily Broken (Expected)**
|
|
```bash
|
|
# This is expected and will be fixed in Phase 4
|
|
# Document that Micropub is non-functional during migration
|
|
```
|
|
|
|
### Verification Commands
|
|
```bash
|
|
# Check for token generation references
|
|
grep -r "generate_token\|issue_token" /home/phil/Projects/starpunk/
|
|
# Should be empty
|
|
|
|
# Verify exception cleanup
|
|
grep -r "InvalidAuthorizationCodeError" /home/phil/Projects/starpunk/
|
|
# Should be empty
|
|
```
|
|
|
|
---
|
|
|
|
## Phase 3: Database Schema Simplification (2 hours)
|
|
|
|
### Objective
|
|
Remove authorization and token tables from the database.
|
|
|
|
### Tasks
|
|
|
|
#### 3.1 Create Removal Migration (30 min)
|
|
Create `/home/phil/Projects/starpunk/migrations/003_remove_indieauth_tables.sql`:
|
|
```sql
|
|
-- Remove IndieAuth server tables
|
|
BEGIN TRANSACTION;
|
|
|
|
-- Drop dependent objects first
|
|
DROP INDEX IF EXISTS idx_tokens_hash;
|
|
DROP INDEX IF EXISTS idx_tokens_user_id;
|
|
DROP INDEX IF EXISTS idx_tokens_client_id;
|
|
DROP INDEX IF EXISTS idx_auth_codes_code;
|
|
DROP INDEX IF EXISTS idx_auth_codes_user_id;
|
|
|
|
-- Drop tables
|
|
DROP TABLE IF EXISTS tokens CASCADE;
|
|
DROP TABLE IF EXISTS authorization_codes CASCADE;
|
|
|
|
-- Clean up any orphaned sequences
|
|
DROP SEQUENCE IF EXISTS tokens_id_seq;
|
|
DROP SEQUENCE IF EXISTS authorization_codes_id_seq;
|
|
|
|
COMMIT;
|
|
```
|
|
|
|
#### 3.2 Run Migration (30 min)
|
|
```bash
|
|
# Backup database first
|
|
pg_dump $DATABASE_URL > backup_before_removal.sql
|
|
|
|
# Run migration
|
|
uv run python -m starpunk.migrate
|
|
```
|
|
|
|
#### 3.3 Update Schema Documentation (30 min)
|
|
Update `/home/phil/Projects/starpunk/docs/design/database-schema.md`:
|
|
- Remove token table documentation
|
|
- Remove authorization_codes table documentation
|
|
- Update ER diagram
|
|
|
|
#### 3.4 Remove Old Migration (30 min)
|
|
```bash
|
|
# Archive old migration
|
|
mv /home/phil/Projects/starpunk/migrations/002_secure_tokens_and_authorization_codes.sql \
|
|
/home/phil/Projects/starpunk/migrations/archive/
|
|
```
|
|
|
|
### Acceptance Criteria
|
|
|
|
✅ **Tables Removed**
|
|
```sql
|
|
-- Connect to database and verify
|
|
\dt
|
|
-- Should NOT list 'tokens' or 'authorization_codes'
|
|
```
|
|
|
|
✅ **No Foreign Key Errors**
|
|
```sql
|
|
-- Check for orphaned constraints
|
|
SELECT conname FROM pg_constraint
|
|
WHERE conname LIKE '%token%' OR conname LIKE '%auth%';
|
|
-- Should return minimal results (only auth_state related)
|
|
```
|
|
|
|
✅ **Application Starts**
|
|
```bash
|
|
uv run python -m starpunk
|
|
# No database connection errors
|
|
```
|
|
|
|
✅ **Admin Functions Work**
|
|
- Can log in
|
|
- Can create posts
|
|
- Sessions persist
|
|
|
|
### Rollback Plan
|
|
```bash
|
|
# If issues arise
|
|
psql $DATABASE_URL < backup_before_removal.sql
|
|
# Re-run old migration
|
|
psql $DATABASE_URL < /home/phil/Projects/starpunk/migrations/archive/002_secure_tokens_and_authorization_codes.sql
|
|
```
|
|
|
|
---
|
|
|
|
## Phase 4: External Token Verification (4 hours)
|
|
|
|
### Objective
|
|
Replace internal token verification with external provider verification.
|
|
|
|
### Tasks
|
|
|
|
#### 4.1 Implement External Verification (2 hours)
|
|
Create new verification in `/home/phil/Projects/starpunk/starpunk/micropub.py`:
|
|
```python
|
|
import hashlib
|
|
import httpx
|
|
from typing import Optional, Dict, Any
|
|
from flask import current_app
|
|
|
|
# Simple in-memory cache
|
|
_token_cache = {}
|
|
|
|
def verify_token(bearer_token: str) -> Optional[Dict[str, Any]]:
|
|
"""Verify token with external endpoint"""
|
|
# Check cache
|
|
token_hash = hashlib.sha256(bearer_token.encode()).hexdigest()
|
|
if token_hash in _token_cache:
|
|
data, expiry = _token_cache[token_hash]
|
|
if time.time() < expiry:
|
|
return data
|
|
del _token_cache[token_hash]
|
|
|
|
# Verify with external endpoint
|
|
endpoint = current_app.config.get('TOKEN_ENDPOINT')
|
|
if not endpoint:
|
|
return None
|
|
|
|
try:
|
|
response = httpx.get(
|
|
endpoint,
|
|
headers={'Authorization': f'Bearer {bearer_token}'},
|
|
timeout=5.0
|
|
)
|
|
|
|
if response.status_code != 200:
|
|
return None
|
|
|
|
data = response.json()
|
|
|
|
# Validate response
|
|
if data.get('me') != current_app.config.get('ADMIN_ME'):
|
|
return None
|
|
|
|
if 'create' not in data.get('scope', '').split():
|
|
return None
|
|
|
|
# Cache for 5 minutes
|
|
_token_cache[token_hash] = (data, time.time() + 300)
|
|
|
|
return data
|
|
|
|
except Exception as e:
|
|
current_app.logger.error(f"Token verification failed: {e}")
|
|
return None
|
|
```
|
|
|
|
#### 4.2 Update Configuration (30 min)
|
|
In `/home/phil/Projects/starpunk/starpunk/config.py`:
|
|
```python
|
|
# External IndieAuth settings
|
|
TOKEN_ENDPOINT = os.getenv('TOKEN_ENDPOINT', 'https://tokens.indieauth.com/token')
|
|
ADMIN_ME = os.getenv('ADMIN_ME') # Required
|
|
|
|
# Validate configuration
|
|
if not ADMIN_ME:
|
|
raise ValueError("ADMIN_ME must be configured")
|
|
```
|
|
|
|
#### 4.3 Remove Old Token Module (30 min)
|
|
```bash
|
|
rm /home/phil/Projects/starpunk/starpunk/tokens.py
|
|
```
|
|
|
|
#### 4.4 Update Tests (1 hour)
|
|
Update `/home/phil/Projects/starpunk/tests/test_micropub.py`:
|
|
```python
|
|
@patch('starpunk.micropub.httpx.get')
|
|
def test_external_token_verification(mock_get):
|
|
mock_response = Mock()
|
|
mock_response.status_code = 200
|
|
mock_response.json.return_value = {
|
|
'me': 'https://example.com',
|
|
'scope': 'create update'
|
|
}
|
|
mock_get.return_value = mock_response
|
|
|
|
# Test verification
|
|
result = verify_token('test-token')
|
|
assert result is not None
|
|
assert result['me'] == 'https://example.com'
|
|
```
|
|
|
|
### Acceptance Criteria
|
|
|
|
✅ **External Verification Works**
|
|
```bash
|
|
# With a valid token from tokens.indieauth.com
|
|
curl -X POST http://localhost:5000/micropub \
|
|
-H "Authorization: Bearer VALID_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"type": ["h-entry"], "properties": {"content": ["Test"]}}'
|
|
# Should return 201 Created
|
|
```
|
|
|
|
✅ **Invalid Tokens Rejected**
|
|
```bash
|
|
curl -X POST http://localhost:5000/micropub \
|
|
-H "Authorization: Bearer INVALID_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"type": ["h-entry"], "properties": {"content": ["Test"]}}'
|
|
# Should return 403 Forbidden
|
|
```
|
|
|
|
✅ **Token Caching Works**
|
|
```python
|
|
# In test environment
|
|
token = "test-token"
|
|
result1 = verify_token(token) # External call
|
|
result2 = verify_token(token) # Should use cache
|
|
# Verify only one external call made
|
|
```
|
|
|
|
✅ **Configuration Validated**
|
|
```bash
|
|
# Without ADMIN_ME set
|
|
unset ADMIN_ME
|
|
uv run python -m starpunk
|
|
# Should fail with clear error message
|
|
```
|
|
|
|
### Performance Verification
|
|
```bash
|
|
# Measure token verification time
|
|
time curl -X GET http://localhost:5000/micropub \
|
|
-H "Authorization: Bearer VALID_TOKEN" \
|
|
-w "\nTime: %{time_total}s\n"
|
|
# First call: <500ms
|
|
# Cached calls: <50ms
|
|
```
|
|
|
|
---
|
|
|
|
## Phase 5: Documentation and Discovery (2 hours)
|
|
|
|
### Objective
|
|
Update all documentation and add proper IndieAuth discovery headers.
|
|
|
|
### Tasks
|
|
|
|
#### 5.1 Add Discovery Links (30 min)
|
|
In `/home/phil/Projects/starpunk/templates/base.html`:
|
|
```html
|
|
<head>
|
|
<!-- Existing head content -->
|
|
|
|
<!-- IndieAuth Discovery -->
|
|
<link rel="authorization_endpoint" href="https://indieauth.com/auth">
|
|
<link rel="token_endpoint" href="{{ config.TOKEN_ENDPOINT }}">
|
|
<link rel="micropub" href="{{ url_for('micropub.micropub_endpoint', _external=True) }}">
|
|
</head>
|
|
```
|
|
|
|
#### 5.2 Update User Documentation (45 min)
|
|
Create `/home/phil/Projects/starpunk/docs/user-guide/indieauth-setup.md`:
|
|
```markdown
|
|
# Setting Up IndieAuth for StarPunk
|
|
|
|
## Quick Start
|
|
|
|
1. Add these links to your personal website's HTML:
|
|
```html
|
|
<link rel="authorization_endpoint" href="https://indieauth.com/auth">
|
|
<link rel="token_endpoint" href="https://tokens.indieauth.com/token">
|
|
<link rel="micropub" href="https://your-starpunk.com/micropub">
|
|
```
|
|
|
|
2. Configure StarPunk:
|
|
```ini
|
|
ADMIN_ME=https://your-website.com
|
|
TOKEN_ENDPOINT=https://tokens.indieauth.com/token
|
|
```
|
|
|
|
3. Use any Micropub client!
|
|
```
|
|
|
|
#### 5.3 Update README (15 min)
|
|
- Remove references to built-in authorization
|
|
- Add "Prerequisites" section about external IndieAuth
|
|
- Update configuration examples
|
|
|
|
#### 5.4 Update CHANGELOG (15 min)
|
|
```markdown
|
|
## [0.5.0] - 2025-11-24
|
|
|
|
### BREAKING CHANGES
|
|
- Removed built-in IndieAuth authorization server
|
|
- Removed token issuance functionality
|
|
- All existing tokens are invalidated
|
|
|
|
### Changed
|
|
- Token verification now uses external IndieAuth providers
|
|
- Simplified database schema (removed token tables)
|
|
- Reduced codebase by ~500 lines
|
|
|
|
### Added
|
|
- Support for external token endpoints
|
|
- Token verification caching for performance
|
|
- IndieAuth discovery links in HTML
|
|
|
|
### Migration Guide
|
|
Users must now:
|
|
1. Configure external IndieAuth provider
|
|
2. Re-authenticate with Micropub clients
|
|
3. Update ADMIN_ME configuration
|
|
```
|
|
|
|
#### 5.5 Version Bump (15 min)
|
|
Update `/home/phil/Projects/starpunk/starpunk/__init__.py`:
|
|
```python
|
|
__version__ = "0.5.0" # Breaking change per versioning strategy
|
|
```
|
|
|
|
### Acceptance Criteria
|
|
|
|
✅ **Discovery Links Present**
|
|
```bash
|
|
curl http://localhost:5000/ | grep -E "authorization_endpoint|token_endpoint|micropub"
|
|
# Should show all three link tags
|
|
```
|
|
|
|
✅ **Documentation Complete**
|
|
- [ ] User guide explains external provider setup
|
|
- [ ] README reflects new architecture
|
|
- [ ] CHANGELOG documents breaking changes
|
|
- [ ] Migration guide provided
|
|
|
|
✅ **Version Updated**
|
|
```bash
|
|
uv run python -c "import starpunk; print(starpunk.__version__)"
|
|
# Should output: 0.5.0
|
|
```
|
|
|
|
✅ **Examples Work**
|
|
- [ ] Example configuration in docs is valid
|
|
- [ ] HTML snippet in docs is correct
|
|
- [ ] Micropub client setup instructions tested
|
|
|
|
---
|
|
|
|
## Final Validation Checklist
|
|
|
|
### System Health
|
|
- [ ] Server starts without errors
|
|
- [ ] Admin can log in
|
|
- [ ] Admin can create posts
|
|
- [ ] Micropub endpoint responds
|
|
- [ ] Valid tokens accepted
|
|
- [ ] Invalid tokens rejected
|
|
- [ ] HTML has discovery links
|
|
|
|
### Code Quality
|
|
- [ ] No orphaned imports
|
|
- [ ] No references to removed code
|
|
- [ ] Tests pass with >90% coverage
|
|
- [ ] No security warnings
|
|
|
|
### Performance
|
|
- [ ] Token verification <500ms
|
|
- [ ] Cached verification <50ms
|
|
- [ ] Memory usage stable
|
|
- [ ] No database deadlocks
|
|
|
|
### Documentation
|
|
- [ ] Architecture docs updated
|
|
- [ ] User guide complete
|
|
- [ ] API docs accurate
|
|
- [ ] CHANGELOG updated
|
|
- [ ] Version bumped
|
|
|
|
### Database
|
|
- [ ] Old tables removed
|
|
- [ ] No orphaned constraints
|
|
- [ ] Migration successful
|
|
- [ ] Backup available
|
|
|
|
## Rollback Decision Tree
|
|
|
|
```
|
|
Issue Detected?
|
|
├─ During Phase 1-2?
|
|
│ └─ Git revert commits
|
|
│ └─ Restart server
|
|
├─ During Phase 3?
|
|
│ └─ Restore database backup
|
|
│ └─ Git revert commits
|
|
│ └─ Restart server
|
|
└─ During Phase 4-5?
|
|
└─ Critical issue?
|
|
├─ Yes: Full rollback
|
|
│ └─ Restore DB + revert code
|
|
└─ No: Fix forward
|
|
└─ Patch issue
|
|
└─ Continue deployment
|
|
```
|
|
|
|
## Success Metrics
|
|
|
|
### Quantitative
|
|
- **Lines removed**: >500
|
|
- **Test coverage**: >90%
|
|
- **Token verification**: <500ms
|
|
- **Cache hit rate**: >90%
|
|
- **Memory stable**: <100MB
|
|
|
|
### Qualitative
|
|
- **Simpler architecture**: Clear separation of concerns
|
|
- **Better security**: Specialized providers handle auth
|
|
- **Less maintenance**: No auth code to maintain
|
|
- **User flexibility**: Choice of providers
|
|
- **Standards compliant**: Pure Micropub server
|
|
|
|
## Risk Matrix
|
|
|
|
| Risk | Probability | Impact | Mitigation |
|
|
|------|------------|---------|------------|
|
|
| Breaking existing tokens | Certain | Medium | Clear communication, migration guide |
|
|
| External service down | Low | High | Token caching, timeout handling |
|
|
| User confusion | Medium | Low | Comprehensive documentation |
|
|
| Performance degradation | Low | Medium | Caching layer, monitoring |
|
|
| Security vulnerability | Low | High | Use established providers |
|
|
|
|
---
|
|
|
|
**Document Version**: 1.0
|
|
**Created**: 2025-11-24
|
|
**Author**: StarPunk Architecture Team
|
|
**Status**: Ready for Implementation |