Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cbef0c1561 |
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.9.3] - 2025-11-22
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **IndieAuth token exchange missing grant_type**: Added required `grant_type=authorization_code` parameter to token exchange request
|
||||||
|
- OAuth 2.0 spec requires this parameter for authorization code flow
|
||||||
|
- Some IndieAuth providers reject token exchange without this parameter
|
||||||
|
- Fixes authentication failures with spec-compliant IndieAuth providers
|
||||||
|
|
||||||
## [0.9.2] - 2025-11-22
|
## [0.9.2] - 2025-11-22
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
# ADR-022: IndieAuth Token Exchange Compliance
|
||||||
|
|
||||||
|
## Status
|
||||||
|
Accepted
|
||||||
|
|
||||||
|
## Context
|
||||||
|
StarPunk's IndieAuth implementation is failing to authenticate with certain providers (specifically gondulf.thesatelliteoflove.com) during the token exchange phase. The provider is rejecting our token exchange requests with a "missing grant_type" error.
|
||||||
|
|
||||||
|
Our current implementation sends:
|
||||||
|
- `code`
|
||||||
|
- `client_id`
|
||||||
|
- `redirect_uri`
|
||||||
|
- `code_verifier` (for PKCE)
|
||||||
|
|
||||||
|
But does NOT include `grant_type=authorization_code`.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
StarPunk MUST include `grant_type=authorization_code` in all token exchange requests to be compliant with both OAuth 2.0 RFC 6749 and IndieAuth specifications.
|
||||||
|
|
||||||
|
## Rationale
|
||||||
|
|
||||||
|
### OAuth 2.0 RFC 6749 Compliance
|
||||||
|
RFC 6749 Section 4.1.3 explicitly states that `grant_type` is a REQUIRED parameter with the value MUST be set to "authorization_code" for the authorization code grant flow.
|
||||||
|
|
||||||
|
### IndieAuth Specification
|
||||||
|
While the IndieAuth specification (W3C TR) doesn't use explicit RFC 2119 language (MUST/REQUIRED) for the grant_type parameter, it:
|
||||||
|
1. Lists `grant_type=authorization_code` as part of the token request parameters in Section 6.3.1
|
||||||
|
2. Shows it in all examples (Example 12)
|
||||||
|
3. States that IndieAuth "builds upon the OAuth 2.0 [RFC6749] Framework"
|
||||||
|
|
||||||
|
Since IndieAuth builds on OAuth 2.0, and OAuth 2.0 requires this parameter, IndieAuth implementations should include it.
|
||||||
|
|
||||||
|
### Provider Compliance
|
||||||
|
The provider (gondulf.thesatelliteoflove.com) is **correctly following the specifications** by requiring the `grant_type` parameter.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
### Positive
|
||||||
|
- Full compliance with OAuth 2.0 RFC 6749
|
||||||
|
- Compatibility with all spec-compliant IndieAuth providers
|
||||||
|
- Clear, standard-compliant token exchange requests
|
||||||
|
|
||||||
|
### Negative
|
||||||
|
- Requires immediate code change to add the missing parameter
|
||||||
|
- May reveal other non-compliant providers that don't check for this parameter
|
||||||
|
|
||||||
|
## Implementation Requirements
|
||||||
|
|
||||||
|
The token exchange request MUST include these parameters:
|
||||||
|
```
|
||||||
|
grant_type=authorization_code # REQUIRED by OAuth 2.0
|
||||||
|
code={authorization_code} # REQUIRED
|
||||||
|
client_id={client_url} # REQUIRED
|
||||||
|
redirect_uri={redirect_url} # REQUIRED if used in initial request
|
||||||
|
me={user_profile_url} # REQUIRED by IndieAuth (extension to OAuth)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Note on PKCE
|
||||||
|
The `code_verifier` parameter currently being sent is NOT part of the IndieAuth specification. IndieAuth does not mention PKCE (RFC 7636) support. However:
|
||||||
|
- Including it shouldn't break compliant providers (they should ignore unknown parameters)
|
||||||
|
- It provides additional security for public clients
|
||||||
|
- Consider making PKCE optional or detecting provider support
|
||||||
|
|
||||||
|
## Alternatives Considered
|
||||||
|
|
||||||
|
### Alternative 1: Argue for Optional grant_type
|
||||||
|
**Rejected**: While IndieAuth could theoretically make grant_type optional since there's only one grant type, this would break compatibility with OAuth 2.0 compliant libraries and providers.
|
||||||
|
|
||||||
|
### Alternative 2: Provider-specific workarounds
|
||||||
|
**Rejected**: Creating provider-specific code paths would violate the principle of standards compliance and create maintenance burden.
|
||||||
|
|
||||||
|
## Recommendation
|
||||||
|
|
||||||
|
**Immediate Action Required**:
|
||||||
|
1. Add `grant_type=authorization_code` to all token exchange requests
|
||||||
|
2. Maintain the existing parameters
|
||||||
|
3. Consider making PKCE optional or auto-detecting provider support
|
||||||
|
|
||||||
|
**StarPunk is at fault** - the implementation is missing a required OAuth 2.0 parameter that IndieAuth inherits.
|
||||||
|
|
||||||
|
## References
|
||||||
|
- [OAuth 2.0 RFC 6749 Section 4.1.3](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3)
|
||||||
|
- [IndieAuth W3C TR Section 6.3.1](https://www.w3.org/TR/indieauth/#token-request)
|
||||||
|
- [PKCE RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636) (not part of IndieAuth spec)
|
||||||
68
docs/reports/2025-11-22-grant-type-fix.md
Normal file
68
docs/reports/2025-11-22-grant-type-fix.md
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# IndieAuth Token Exchange grant_type Fix
|
||||||
|
|
||||||
|
**Date**: 2025-11-22
|
||||||
|
**Version**: 0.9.3
|
||||||
|
**Type**: Bug Fix
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Added the required `grant_type=authorization_code` parameter to the IndieAuth token exchange request.
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
The token exchange request in `starpunk/auth.py` was missing the `grant_type` parameter. Per OAuth 2.0 spec (RFC 6749 Section 4.1.3), the token exchange request MUST include:
|
||||||
|
|
||||||
|
```
|
||||||
|
grant_type=authorization_code
|
||||||
|
```
|
||||||
|
|
||||||
|
Some IndieAuth providers that strictly validate OAuth 2.0 compliance would reject the token exchange request without this parameter.
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
Added `"grant_type": "authorization_code"` to the `token_exchange_data` dictionary in the `handle_callback` function.
|
||||||
|
|
||||||
|
### Before
|
||||||
|
|
||||||
|
```python
|
||||||
|
token_exchange_data = {
|
||||||
|
"code": code,
|
||||||
|
"client_id": current_app.config["SITE_URL"],
|
||||||
|
"redirect_uri": f"{current_app.config['SITE_URL']}auth/callback",
|
||||||
|
"code_verifier": code_verifier,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### After
|
||||||
|
|
||||||
|
```python
|
||||||
|
token_exchange_data = {
|
||||||
|
"grant_type": "authorization_code",
|
||||||
|
"code": code,
|
||||||
|
"client_id": current_app.config["SITE_URL"],
|
||||||
|
"redirect_uri": f"{current_app.config['SITE_URL']}auth/callback",
|
||||||
|
"code_verifier": code_verifier,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Files Modified
|
||||||
|
|
||||||
|
1. **`starpunk/auth.py`** (line 412)
|
||||||
|
- Added `"grant_type": "authorization_code"` to token_exchange_data
|
||||||
|
|
||||||
|
2. **`starpunk/__init__.py`** (line 156)
|
||||||
|
- Version bumped from 0.9.2 to 0.9.3
|
||||||
|
|
||||||
|
3. **`CHANGELOG.md`**
|
||||||
|
- Added 0.9.3 release notes
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
- Module imports successfully
|
||||||
|
- Pre-existing test failures are unrelated (OAuth metadata and h-app tests for removed functionality)
|
||||||
|
- No new test failures introduced
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- RFC 6749 Section 4.1.3: Access Token Request
|
||||||
|
- IndieAuth specification
|
||||||
@@ -153,5 +153,5 @@ def create_app(config=None):
|
|||||||
|
|
||||||
# Package version (Semantic Versioning 2.0.0)
|
# Package version (Semantic Versioning 2.0.0)
|
||||||
# See docs/standards/versioning-strategy.md for details
|
# See docs/standards/versioning-strategy.md for details
|
||||||
__version__ = "0.9.2"
|
__version__ = "0.9.3"
|
||||||
__version_info__ = (0, 9, 2)
|
__version_info__ = (0, 9, 3)
|
||||||
|
|||||||
@@ -409,6 +409,7 @@ def handle_callback(code: str, state: str, iss: Optional[str] = None) -> Optiona
|
|||||||
|
|
||||||
# Prepare token exchange request with PKCE verifier
|
# Prepare token exchange request with PKCE verifier
|
||||||
token_exchange_data = {
|
token_exchange_data = {
|
||||||
|
"grant_type": "authorization_code",
|
||||||
"code": code,
|
"code": code,
|
||||||
"client_id": current_app.config["SITE_URL"],
|
"client_id": current_app.config["SITE_URL"],
|
||||||
"redirect_uri": f"{current_app.config['SITE_URL']}auth/callback",
|
"redirect_uri": f"{current_app.config['SITE_URL']}auth/callback",
|
||||||
|
|||||||
Reference in New Issue
Block a user