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>
7.2 KiB
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:
{
"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/):
-
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_typeparameter is used - Response contains only
{"me": "user-url"}
-
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_codeparameter - 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):
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:
- Uses
/tokenendpoint instead of authorization endpoint - Includes
grant_typeparameter which should not be present for authentication-only flows
Decision
StarPunk must correct its IndieAuth authentication implementation to comply with the specification:
- Use the authorization endpoint for code redemption in authentication-only flows
- Remove the
grant_typeparameter from authentication requests - Keep PKCE parameters (
code_verifier) as they are still required
Rationale
Why This Matters
- Standards Compliance: The IndieAuth specification clearly distinguishes between authentication and authorization flows
- Provider Compatibility: Some providers (like gondulf) strictly enforce the specification
- 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 (
meURL) - 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:
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:
- Discover the authorization endpoint from the provider's metadata
- Use the same endpoint for both authorization initiation and code redemption
- 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:
- IndieLogin.com - Current provider (should continue working)
- gondulf.thesatelliteoflove.com - Strict implementation
- tokens.indieauth.com - Token-only endpoint (should fail for auth)
- 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: Authorization Code Verification for authentication flows
- IndieAuth Specification Section 6.3: Token Endpoint for authorization flows
- IndieAuth Authentication vs Authorization: Community documentation
- ADR-021: IndieAuth Provider Strategy: Related architectural decision
Document Version: 1.0 Created: 2025-11-22 Author: StarPunk Architecture Team Status: Accepted