Files
StarPunk/docs/architecture/indieauth-removal-phases.md
Phil Skentelbery a3bac86647 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>
2025-11-24 17:23:46 -07:00

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:

  • InvalidAuthorizationCodeError
  • ExpiredAuthorizationCodeError
  • 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

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">
  1. Configure StarPunk:

    ADMIN_ME=https://your-website.com
    TOKEN_ENDPOINT=https://tokens.indieauth.com/token
    
  2. 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