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>
15 KiB
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)
# 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)
# 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
uv run python -m starpunk
# No import errors or missing route errors
✅ Admin Login Works
# Navigate to /admin/login
# Can still authenticate via IndieLogin.com
# Session created successfully
✅ No Authorization Endpoint
curl -I http://localhost:5000/auth/authorization
# Should return 404 Not Found
✅ Tests Pass (Remaining)
uv run pytest tests/ -k "not authorization and not pkce"
# All remaining tests pass
Verification Commands
# 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)
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:
InvalidAuthorizationCodeErrorExpiredAuthorizationCodeError- Update error handling to use generic exceptions
Acceptance Criteria
✅ No Token Endpoint
curl -I http://localhost:5000/auth/token
# Should return 404 Not Found
✅ No Token Generation Code
grep -r "create_access_token\|create_authorization_code" /home/phil/Projects/starpunk/starpunk/
# Should return nothing (except in comments)
✅ Server Still Runs
uv run python -m starpunk
# No import errors
✅ Micropub Temporarily Broken (Expected)
# This is expected and will be fixed in Phase 4
# Document that Micropub is non-functional during migration
Verification Commands
# 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:
-- 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)
# 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)
# 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
-- Connect to database and verify
\dt
-- Should NOT list 'tokens' or 'authorization_codes'
✅ No Foreign Key Errors
-- 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
uv run python -m starpunk
# No database connection errors
✅ Admin Functions Work
- Can log in
- Can create posts
- Sessions persist
Rollback Plan
# 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:
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:
# 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)
rm /home/phil/Projects/starpunk/starpunk/tokens.py
4.4 Update Tests (1 hour)
Update /home/phil/Projects/starpunk/tests/test_micropub.py:
@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
# 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
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
# 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
# Without ADMIN_ME set
unset ADMIN_ME
uv run python -m starpunk
# Should fail with clear error message
Performance Verification
# 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:
<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:
# 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">
-
Configure StarPunk:
ADMIN_ME=https://your-website.com TOKEN_ENDPOINT=https://tokens.indieauth.com/token -
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:
__version__ = "0.5.0" # Breaking change per versioning strategy
Acceptance Criteria
✅ Discovery Links Present
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
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