# ADR-025: IndieAuth Correct Implementation Based on IndieLogin.com API

## Status

Accepted

## Context

StarPunk's IndieAuth authentication has been failing in production despite implementing various fixes (ADR-016, ADR-017) including OAuth metadata endpoints and h-app microformats. These implementations were based on misunderstanding the requirements of the specific service we use: IndieLogin.com.

### The Core Problem

We conflated two different things:
1. **Generic IndieAuth specification** - Full OAuth 2.0 with client discovery mechanisms
2. **IndieLogin.com API** - Simplified authentication-only service with specific requirements

IndieLogin.com is a **simplified authentication service**, not a full OAuth 2.0 authorization server. It has specific API requirements that differ from the generic IndieAuth specification.

### What We Misunderstood

1. **Authentication vs Authorization**: IndieLogin.com provides **authentication** (who are you?) not **authorization** (what can you access?). No scopes, no access tokens for API access - just identity verification.

2. **Client Discovery Not Required**: IndieLogin.com accepts any valid `client_id` URL without pre-registration or metadata endpoints. The OAuth metadata endpoint and h-app microformats we added are unnecessary.

3. **PKCE is Mandatory**: IndieLogin.com **requires** PKCE (Proof Key for Code Exchange) parameters for security. Our current implementation lacks this entirely.

4. **Wrong Endpoints**: We're using `/auth` when we should use `/authorize` and `/token`.

### Critical Missing Pieces

Our current implementation in `starpunk/auth.py` is missing:
- PKCE `code_verifier` generation and storage
- PKCE `code_challenge` generation and transmission
- `code_verifier` in token exchange
- Issuer (`iss`) validation
- Correct API endpoints

### Why Previous Fixes Failed

- **ADR-016 (h-app microformats)**: Added client discovery mechanism that IndieLogin.com doesn't use
- **ADR-017 (OAuth metadata endpoint)**: Added OAuth endpoint that IndieLogin.com doesn't check
- **Original implementation**: Missing PKCE, wrong endpoints, incomplete parameter set

## Decision

**Implement IndieAuth authentication following the IndieLogin.com API specification exactly**, specifically:

1. **Implement PKCE Flow**
   - Generate cryptographically secure `code_verifier` (43-character random string)
   - Generate `code_challenge` (SHA256 hash of verifier, base64-url encoded)
   - Store `code_verifier` with state token in database
   - Send `code_challenge` and `code_challenge_method=S256` in authorization request
   - Send `code_verifier` in token exchange request

2. **Use Correct IndieLogin.com Endpoints**
   - Authorization: `https://indielogin.com/authorize` (not `/auth`)
   - Token exchange: `https://indielogin.com/token` (not `/auth`)

3. **Required Parameters for Authorization Request**
   - `client_id` - Our application URL
   - `redirect_uri` - Our callback URL (must be on same domain)
   - `state` - Random CSRF protection token
   - `code_challenge` - PKCE challenge
   - `code_challenge_method` - Must be `S256`
   - `me` - User's URL (optional, prompts if omitted)

4. **Required Parameters for Token Exchange**
   - `code` - Authorization code from callback
   - `client_id` - Our application URL (same as authorization)
   - `redirect_uri` - Our callback URL (same as authorization)
   - `code_verifier` - Original PKCE verifier

5. **Validate Callback Parameters**
   - Verify `state` matches stored value (CSRF protection)
   - Verify `iss` equals `https://indielogin.com/` (issuer validation)
   - Extract `code` for token exchange

6. **Remove Unnecessary Components**
   - Remove OAuth metadata endpoint (`/.well-known/oauth-authorization-server`)
   - Remove h-app microformats markup from templates
   - Remove `indieauth-metadata` link from HTML head
   - Remove unused `response_type` parameter from authorization request

## Rationale

### Why This Approach is Correct

1. **Based on Official Documentation**: Every decision comes directly from https://indielogin.com/api, the authoritative source for the service we use.

2. **PKCE is Non-Negotiable**: IndieLogin.com requires it for security. PKCE prevents authorization code interception attacks, especially important for public clients.

3. **Simple Authentication Flow**: We need identity verification (web sign-in), not resource authorization. IndieLogin.com provides exactly this.

4. **No Client Registration Required**: IndieLogin.com accepts any valid `client_id` URL. Pre-registration mechanisms add complexity without benefit.

5. **Security Best Practices**:
   - State token prevents CSRF attacks
   - PKCE prevents authorization code interception
   - Issuer validation prevents token substitution
   - Single-use tokens prevent replay attacks

### Alignment with Project Principles

1. **Minimal Code**: Removes ~73 lines of unnecessary code (metadata endpoint, microformats)
2. **Standards First**: Follows official IndieLogin.com API specification
3. **"Every line must justify existence"**: Eliminates features that don't serve actual requirements
4. **No Lock-in**: Standard OAuth/PKCE implementation portable to other services

## Consequences

### Positive

1. **Authentication Will Work**: Follows IndieLogin.com API requirements exactly
2. **Simpler Codebase**: Net reduction of ~23 lines after adding PKCE and removing unnecessary features
3. **Better Security**: PKCE protection against authorization code attacks
4. **Standards Compliant**: Proper PKCE implementation per RFC 7636
5. **More Maintainable**: Clearer code with focused purpose
6. **Better Testability**: Well-defined flow with clear inputs/outputs

### Negative

1. **Database Migration Required**: Must add `code_verifier` column to `auth_state` table
   - Mitigation: Simple `ALTER TABLE`, backward compatible with default value

2. **Breaking Change for In-Flight Logins**: Users mid-authentication must restart
   - Mitigation: State tokens expire in 5 minutes anyway, minimal impact
   - Existing sessions remain valid (no logout of authenticated users)

3. **More Complex Auth Flow**: PKCE adds generation/storage/validation steps
   - Mitigation: Security benefit justifies complexity
   - Well-encapsulated in helper functions

### Neutral

1. **Code Changes**: Adds ~50 lines for PKCE, removes ~73 lines of unnecessary features (net -23 lines)
2. **Testing**: More test cases for PKCE, but clearer test boundaries

## Superseded Decisions

This ADR supersedes:

1. **ADR-016: IndieAuth Client Discovery Mechanism**
   - h-app microformats not required by IndieLogin.com
   - Status: Superseded

2. **ADR-017: OAuth Client ID Metadata Document Implementation**
   - OAuth metadata endpoint not required by IndieLogin.com
   - Status: Superseded

This ADR corrects the implementation details (but not the concept) in:

3. **ADR-005: IndieLogin Authentication Integration**
   - Authentication flow concept remains valid
   - Implementation corrected: added PKCE, corrected endpoints, added issuer validation
   - Status: Accepted (with implementation note)

## Version Impact

**Change Type**: Critical bug fix (authentication completely broken in production)

**Semantic Versioning Analysis**:
- **Fixes broken feature**: IndieAuth authentication
- **Removes features**: OAuth metadata endpoint (added in v0.7.0, never functioned)
- **Adds security enhancement**: PKCE implementation
- **Database schema change**: Adding column (backward compatible with default)

**Version Decision**: See versioning guidance document for final determination based on current release state.

## Compliance

### IndieLogin.com API Requirements
- Uses `/authorize` endpoint for authentication initiation
- Uses `/token` endpoint for code exchange
- Sends all required parameters per API documentation
- Implements required PKCE flow
- Validates state and issuer per security recommendations

### PKCE Specification (RFC 7636)
- code_verifier: 43-128 character URL-safe random string
- code_challenge: Base64-URL encoded SHA256 hash
- code_challenge_method: S256
- Proper storage and single-use validation

### Project Standards
- Minimal code principle
- Standards-first approach
- Security best practices
- Clear documentation of decisions

## Implementation Notes

The technical implementation is documented in:
- **Design Document**: `/home/phil/Projects/starpunk/docs/designs/indieauth-pkce-authentication.md` - Technical specifications, flow diagrams, PKCE implementation details
- **Implementation Guide**: Included in design document - Step-by-step developer instructions, code changes, testing strategy

## References

### Primary Source
- **IndieLogin.com API Documentation**: https://indielogin.com/api
  - Authoritative source for all implementation decisions

### Supporting Specifications
- **PKCE Specification (RFC 7636)**: https://www.rfc-editor.org/rfc/rfc7636
- **OAuth 2.0 (RFC 6749)**: https://www.rfc-editor.org/rfc/rfc6749
- **IndieAuth Specification**: https://www.w3.org/TR/indieauth/ (context only)

### Internal Documentation
- ADR-005: IndieLogin Authentication Integration (conceptual flow)
- ADR-010: Authentication Module Design
- ADR-016: IndieAuth Client Discovery Mechanism (superseded)
- ADR-017: OAuth Client ID Metadata Document (superseded)

## What We Learned

1. **Read the specific API documentation first**, not generic specifications
2. **Service-specific implementations matter**: IndieLogin.com is not a generic IndieAuth server
3. **PKCE is increasingly required**: Modern OAuth services mandate it for public clients
4. **Authentication ≠ Authorization**: Different use cases require different OAuth flows
5. **Simpler is often correct**: Unnecessary features indicate misunderstanding of requirements

---

**Decided**: 2025-11-19
**Author**: StarPunk Architect
**Supersedes**: ADR-016, ADR-017
**Corrects**: ADR-005 (implementation details)
