feat(token): implement GET /token for token verification
Implements W3C IndieAuth Section 6.3 token verification endpoint. The token endpoint now supports both: - POST: Issue new tokens (authorization code exchange) - GET: Verify existing tokens (resource server validation) Changes: - Added GET handler to /token endpoint - Extracts Bearer token from Authorization header (RFC 6750) - Returns JSON with me, client_id, scope - Returns 401 with WWW-Authenticate for invalid tokens - 11 new tests covering all verification scenarios All 533 tests passing. Resolves critical P0 blocker for v1.0.0. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
166
docs/decisions/ADR-013-token-verification-endpoint.md
Normal file
166
docs/decisions/ADR-013-token-verification-endpoint.md
Normal file
@@ -0,0 +1,166 @@
|
||||
# ADR-013: Token Verification Endpoint Missing - Critical Compliance Issue
|
||||
|
||||
Date: 2025-11-25
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
|
||||
The user has identified a critical compliance issue with Gondulf's IndieAuth implementation. The W3C IndieAuth specification requires that token endpoints support both POST (for issuing tokens) and GET (for verifying tokens). Currently, Gondulf only implements the POST method for token issuance, returning HTTP 405 (Method Not Allowed) for GET requests.
|
||||
|
||||
### W3C IndieAuth Specification Requirements
|
||||
|
||||
Per the W3C IndieAuth specification Section 6.3 (Token Verification):
|
||||
- https://www.w3.org/TR/indieauth/#token-verification
|
||||
|
||||
The specification states:
|
||||
> "If an external endpoint needs to verify that an access token is valid, it MUST make a GET request to the token endpoint containing an HTTP Authorization header with the Bearer Token according to [RFC6750]."
|
||||
|
||||
Example from the specification:
|
||||
```
|
||||
GET https://example.org/token
|
||||
Authorization: Bearer xxxxxxxx
|
||||
```
|
||||
|
||||
Required Response Format:
|
||||
```json
|
||||
{
|
||||
"me": "https://example.com",
|
||||
"client_id": "https://client.example.com",
|
||||
"scope": "create update"
|
||||
}
|
||||
```
|
||||
|
||||
### Current Implementation Analysis
|
||||
|
||||
1. **Token Endpoint (`/home/phil/Projects/Gondulf/src/gondulf/routers/token.py`)**:
|
||||
- Only implements `@router.post("/token")`
|
||||
- No GET handler exists
|
||||
- Returns 405 Method Not Allowed for GET requests
|
||||
|
||||
2. **Token Service (`/home/phil/Projects/Gondulf/src/gondulf/services/token_service.py`)**:
|
||||
- Has `validate_token()` method already implemented
|
||||
- Returns token metadata (me, client_id, scope)
|
||||
- Ready to support verification endpoint
|
||||
|
||||
3. **Architecture Documents**:
|
||||
- Token verification identified in backlog as P1 priority
|
||||
- Listed as separate endpoint `/token/verify` (incorrect)
|
||||
- Not included in v1.0.0 scope
|
||||
|
||||
### Reference Implementation Analysis
|
||||
|
||||
IndieLogin.com (PHP reference) only implements POST `/token` for authentication-only flows. However, this is because IndieLogin is authentication-only and doesn't issue access tokens for resource access. Gondulf DOES issue access tokens, making token verification mandatory.
|
||||
|
||||
## Decision
|
||||
|
||||
**This is a CRITICAL COMPLIANCE BUG that MUST be fixed for v1.0.0.**
|
||||
|
||||
The token endpoint MUST support GET requests for token verification per the W3C IndieAuth specification. This is not optional - it's a core requirement for any implementation that issues access tokens.
|
||||
|
||||
### Implementation Approach
|
||||
|
||||
1. **Same Endpoint, Different Methods**:
|
||||
- GET `/token` - Verify token (with Bearer header)
|
||||
- POST `/token` - Issue token (existing functionality)
|
||||
- NOT a separate `/token/verify` endpoint
|
||||
|
||||
2. **Implementation Details**:
|
||||
```python
|
||||
@router.get("/token")
|
||||
async def verify_token(
|
||||
authorization: str = Header(None),
|
||||
token_service: TokenService = Depends(get_token_service)
|
||||
):
|
||||
"""
|
||||
Verify access token per W3C IndieAuth specification.
|
||||
|
||||
GET /token
|
||||
Authorization: Bearer {token}
|
||||
"""
|
||||
if not authorization or not authorization.startswith("Bearer "):
|
||||
raise HTTPException(401, {"error": "invalid_token"})
|
||||
|
||||
token = authorization[7:] # Remove "Bearer " prefix
|
||||
metadata = token_service.validate_token(token)
|
||||
|
||||
if not metadata:
|
||||
raise HTTPException(401, {"error": "invalid_token"})
|
||||
|
||||
return {
|
||||
"me": metadata["me"],
|
||||
"client_id": metadata["client_id"],
|
||||
"scope": metadata["scope"]
|
||||
}
|
||||
```
|
||||
|
||||
3. **Error Handling**:
|
||||
- Missing/invalid Bearer header: 401 Unauthorized
|
||||
- Invalid/expired token: 401 Unauthorized
|
||||
- Malformed request: 400 Bad Request
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive Consequences
|
||||
|
||||
1. **Full Specification Compliance**: Gondulf will be fully compliant with W3C IndieAuth
|
||||
2. **Micropub Compatibility**: Resource servers like Micropub endpoints can verify tokens
|
||||
3. **Interoperability**: Any IndieAuth-compliant resource server can work with Gondulf
|
||||
4. **Minimal Implementation Effort**: TokenService already has validation logic
|
||||
|
||||
### Negative Consequences
|
||||
|
||||
1. **Scope Creep**: Adds unplanned work to v1.0.0
|
||||
2. **Testing Required**: Need new tests for GET endpoint
|
||||
3. **Documentation Updates**: Must update all token endpoint documentation
|
||||
|
||||
### Impact Assessment
|
||||
|
||||
**Severity**: CRITICAL
|
||||
**Priority**: P0 (Blocker for v1.0.0)
|
||||
**Effort**: Small (1-2 hours)
|
||||
|
||||
Without this endpoint:
|
||||
- Gondulf is NOT a compliant IndieAuth server
|
||||
- Resource servers cannot verify tokens
|
||||
- Micropub/Microsub endpoints will fail
|
||||
- The entire purpose of issuing access tokens is undermined
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
1. **Immediate Actions**:
|
||||
- Add GET handler to token endpoint
|
||||
- Extract Bearer token from Authorization header
|
||||
- Call existing `validate_token()` method
|
||||
- Return required JSON response
|
||||
|
||||
2. **Testing Required**:
|
||||
- Valid token verification
|
||||
- Invalid token handling
|
||||
- Missing Authorization header
|
||||
- Malformed Bearer token
|
||||
- Expired token handling
|
||||
|
||||
3. **Documentation Updates**:
|
||||
- Update token endpoint design
|
||||
- Add verification examples
|
||||
- Update API documentation
|
||||
|
||||
## Related Documents
|
||||
|
||||
- W3C IndieAuth Specification Section 6.3: https://www.w3.org/TR/indieauth/#token-verification
|
||||
- RFC 6750 (Bearer Token Usage): https://datatracker.ietf.org/doc/html/rfc6750
|
||||
- Phase 3 Token Endpoint Design: `/docs/designs/phase-3-token-endpoint.md`
|
||||
- Token Service Implementation: `/src/gondulf/services/token_service.py`
|
||||
|
||||
## Recommendation
|
||||
|
||||
**APPROVED FOR IMMEDIATE IMPLEMENTATION**
|
||||
|
||||
This is not a feature request but a critical compliance bug. The token verification endpoint is a mandatory part of the IndieAuth specification for any server that issues access tokens. Without it, Gondulf cannot claim to be an IndieAuth-compliant server.
|
||||
|
||||
The implementation is straightforward since all the underlying infrastructure exists. The TokenService already has the validation logic, and we just need to expose it via a GET endpoint that reads the Bearer token from the Authorization header.
|
||||
|
||||
This MUST be implemented before v1.0.0 release.
|
||||
Reference in New Issue
Block a user