IndieAuth authentication-only flows should redeem the code at the authorization endpoint, not the token endpoint. The token endpoint is only for authorization flows that need access tokens. - Remove grant_type parameter (only needed for token flows) - Change endpoint from /token to /authorize - Update debug logging to reflect code verification flow 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
188 lines
7.2 KiB
Markdown
188 lines
7.2 KiB
Markdown
# ADR-022: IndieAuth Authentication Endpoint Correction
|
|
|
|
## Status
|
|
Accepted
|
|
|
|
## Context
|
|
|
|
StarPunk is encountering authentication failures with certain IndieAuth providers (specifically gondulf.thesatelliteoflove.com). After investigation, we discovered that StarPunk is incorrectly using the **token endpoint** for authentication-only flows, when it should be using the **authorization endpoint**.
|
|
|
|
### The Problem
|
|
|
|
When attempting to authenticate with gondulf.thesatelliteoflove.com, the provider returns:
|
|
```json
|
|
{
|
|
"error": "invalid_grant",
|
|
"error_description": "Authorization code must be redeemed at the authorization endpoint"
|
|
}
|
|
```
|
|
|
|
StarPunk is currently sending authentication code redemption requests to `/token` when it should be sending them to the authorization endpoint for authentication-only flows.
|
|
|
|
### IndieAuth Specification Analysis
|
|
|
|
According to the W3C IndieAuth specification (https://www.w3.org/TR/indieauth/):
|
|
|
|
1. **Authentication-only flows** (Section 5.4):
|
|
- Used when the client only needs to verify user identity
|
|
- Code redemption happens at the **authorization endpoint**
|
|
- No `grant_type` parameter is used
|
|
- Response contains only `{"me": "user-url"}`
|
|
|
|
2. **Authorization flows** (Section 6.3):
|
|
- Used when the client needs an access token for API access
|
|
- Code redemption happens at the **token endpoint**
|
|
- Requires `grant_type=authorization_code` parameter
|
|
- Response contains access token and user identity
|
|
|
|
### Current StarPunk Implementation
|
|
|
|
StarPunk's current code in `/home/phil/Projects/starpunk/starpunk/auth.py` (lines 410-419):
|
|
|
|
```python
|
|
token_exchange_data = {
|
|
"grant_type": "authorization_code", # WRONG for authentication-only
|
|
"code": code,
|
|
"client_id": current_app.config["SITE_URL"],
|
|
"redirect_uri": f"{current_app.config['SITE_URL']}auth/callback",
|
|
"code_verifier": code_verifier, # PKCE verification
|
|
}
|
|
|
|
token_url = f"{current_app.config['INDIELOGIN_URL']}/token" # WRONG endpoint
|
|
```
|
|
|
|
This implementation has two errors:
|
|
1. Uses `/token` endpoint instead of authorization endpoint
|
|
2. Includes `grant_type` parameter which should not be present for authentication-only flows
|
|
|
|
## Decision
|
|
|
|
StarPunk must correct its IndieAuth authentication implementation to comply with the specification:
|
|
|
|
1. **Use the authorization endpoint** for code redemption in authentication-only flows
|
|
2. **Remove the `grant_type` parameter** from authentication requests
|
|
3. **Keep PKCE parameters** (`code_verifier`) as they are still required
|
|
|
|
## Rationale
|
|
|
|
### Why This Matters
|
|
|
|
1. **Standards Compliance**: The IndieAuth specification clearly distinguishes between authentication and authorization flows
|
|
2. **Provider Compatibility**: Some providers (like gondulf) strictly enforce the specification
|
|
3. **Correct Semantics**: StarPunk only needs to verify admin identity, not obtain an access token
|
|
|
|
### Authentication vs Authorization
|
|
|
|
StarPunk's admin login is an **authentication-only** use case:
|
|
- We only need to verify the admin's identity (`me` URL)
|
|
- We don't need an access token to access external resources
|
|
- We create our own session after successful authentication
|
|
|
|
This is fundamentally different from Micropub client authorization where:
|
|
- External clients need access tokens
|
|
- Tokens are used to authorize API access
|
|
- The token endpoint is the correct choice
|
|
|
|
## Implementation
|
|
|
|
### Required Changes
|
|
|
|
In `/home/phil/Projects/starpunk/starpunk/auth.py`, the `handle_callback` function must be updated:
|
|
|
|
```python
|
|
def handle_callback(code: str, state: str, iss: Optional[str] = None) -> Optional[str]:
|
|
# ... existing state verification code ...
|
|
|
|
# Prepare authentication request (NOT token exchange)
|
|
auth_data = {
|
|
# NO grant_type parameter for authentication-only flows
|
|
"code": code,
|
|
"client_id": current_app.config["SITE_URL"],
|
|
"redirect_uri": f"{current_app.config['SITE_URL']}auth/callback",
|
|
"code_verifier": code_verifier, # PKCE verification still required
|
|
}
|
|
|
|
# Use authorization endpoint (NOT token endpoint)
|
|
# The same endpoint used for the initial authorization request
|
|
auth_url = f"{current_app.config['INDIELOGIN_URL']}/auth" # or /authorize
|
|
|
|
# Exchange code for identity (authentication-only)
|
|
response = httpx.post(
|
|
auth_url,
|
|
data=auth_data,
|
|
timeout=10.0,
|
|
)
|
|
|
|
# Response will be: {"me": "https://user.example.com"}
|
|
# NOT an access token response
|
|
```
|
|
|
|
### Endpoint Discovery Consideration
|
|
|
|
IndieAuth providers may use different paths for their authorization endpoint:
|
|
- IndieLogin.com uses `/auth`
|
|
- Some providers use `/authorize`
|
|
- The gondulf provider appears to use its root domain as the authorization endpoint
|
|
|
|
The correct approach is to:
|
|
1. Discover the authorization endpoint from the provider's metadata
|
|
2. Use the same endpoint for both authorization initiation and code redemption
|
|
3. Store the discovered endpoint during the initial authorization request
|
|
|
|
## Consequences
|
|
|
|
### Positive
|
|
- **Specification Compliance**: Correctly implements IndieAuth authentication flow
|
|
- **Provider Compatibility**: Works with strict IndieAuth implementations
|
|
- **Semantic Correctness**: Uses the right flow for the use case
|
|
|
|
### Negative
|
|
- **Breaking Change**: May affect compatibility with providers that accept both endpoints
|
|
- **Testing Required**: Need to verify with multiple IndieAuth providers
|
|
|
|
### Migration Impact
|
|
- Existing sessions remain valid (no database changes)
|
|
- Only affects new login attempts
|
|
- Should be transparent to users
|
|
|
|
## Testing Strategy
|
|
|
|
Test with multiple IndieAuth providers:
|
|
1. **IndieLogin.com** - Current provider (should continue working)
|
|
2. **gondulf.thesatelliteoflove.com** - Strict implementation
|
|
3. **tokens.indieauth.com** - Token-only endpoint (should fail for auth)
|
|
4. **Self-hosted implementations** - Various compliance levels
|
|
|
|
## Alternatives Considered
|
|
|
|
### Alternative 1: Support Both Endpoints
|
|
Attempt token endpoint first, fall back to authorization endpoint on failure.
|
|
- **Pros**: Maximum compatibility
|
|
- **Cons**: Not specification-compliant, adds complexity
|
|
- **Verdict**: Rejected - violates standards
|
|
|
|
### Alternative 2: Make Endpoint Configurable
|
|
Allow admin to configure which endpoint to use.
|
|
- **Pros**: Flexible for different providers
|
|
- **Cons**: Confusing for users, not needed if we follow spec
|
|
- **Verdict**: Rejected - specification is clear
|
|
|
|
### Alternative 3: Always Use Token Endpoint
|
|
Continue current implementation, document incompatibility.
|
|
- **Pros**: No code changes needed
|
|
- **Cons**: Violates specification, limits provider choice
|
|
- **Verdict**: Rejected - incorrect implementation
|
|
|
|
## References
|
|
|
|
- [IndieAuth Specification Section 5.4](https://www.w3.org/TR/indieauth/#authentication-response): Authorization Code Verification for authentication flows
|
|
- [IndieAuth Specification Section 6.3](https://www.w3.org/TR/indieauth/#token-response): Token Endpoint for authorization flows
|
|
- [IndieAuth Authentication vs Authorization](https://indieweb.org/IndieAuth#Authentication_vs_Authorization): Community documentation
|
|
- [ADR-021: IndieAuth Provider Strategy](/home/phil/Projects/starpunk/docs/decisions/ADR-021-indieauth-provider-strategy.md): Related architectural decision
|
|
|
|
---
|
|
|
|
**Document Version**: 1.0
|
|
**Created**: 2025-11-22
|
|
**Author**: StarPunk Architecture Team
|
|
**Status**: Accepted |