Implements tag/category system backend following microformats2 p-category specification. Database changes: - Migration 008: Add tags and note_tags tables - Normalized tag storage (case-insensitive lookup, display name preserved) - Indexes for performance New module: - starpunk/tags.py: Tag management functions - normalize_tag: Normalize tag strings - get_or_create_tag: Get or create tag records - add_tags_to_note: Associate tags with notes (replaces existing) - get_note_tags: Retrieve note tags (alphabetically ordered) - get_tag_by_name: Lookup tag by normalized name - get_notes_by_tag: Get all notes with specific tag - parse_tag_input: Parse comma-separated tag input Model updates: - Note.tags property (lazy-loaded, prefer pre-loading in routes) - Note.to_dict() add include_tags parameter CRUD updates: - create_note() accepts tags parameter - update_note() accepts tags parameter (None = no change, [] = remove all) Micropub integration: - Pass tags to create_note() (tags already extracted by extract_tags()) - Return tags in q=source response Per design doc: docs/design/v1.3.0/microformats-tags-design.md Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
160 lines
5.0 KiB
Markdown
160 lines
5.0 KiB
Markdown
# IndieAuth Token Verification Diagnosis
|
|
|
|
## Executive Summary
|
|
|
|
**The Problem**: StarPunk is receiving HTTP 405 Method Not Allowed when verifying tokens with gondulf.thesatelliteoflove.com
|
|
|
|
**The Cause**: The gondulf IndieAuth provider does not implement the W3C IndieAuth specification correctly
|
|
|
|
**The Solution**: The provider needs to be fixed - StarPunk's implementation is correct
|
|
|
|
## Why We Make GET Requests
|
|
|
|
You asked: "Why are we making GET requests to these endpoints?"
|
|
|
|
**Answer**: Because the W3C IndieAuth specification explicitly requires GET requests for token verification.
|
|
|
|
### The IndieAuth Token Endpoint Dual Purpose
|
|
|
|
The token endpoint serves two distinct purposes with different HTTP methods:
|
|
|
|
1. **Token Issuance (POST)**
|
|
- Client sends authorization code
|
|
- Server returns new access token
|
|
- State-changing operation
|
|
|
|
2. **Token Verification (GET)**
|
|
- Resource server sends token in Authorization header
|
|
- Token endpoint returns token metadata
|
|
- Read-only operation
|
|
|
|
### Why This Design Makes Sense
|
|
|
|
The specification follows RESTful principles:
|
|
|
|
- **GET** = Read data (verify a token exists and is valid)
|
|
- **POST** = Create/modify data (issue a new token)
|
|
|
|
This is similar to how you might:
|
|
- GET /users/123 to read user information
|
|
- POST /users to create a new user
|
|
|
|
## The Specific Problem
|
|
|
|
### What Should Happen
|
|
```
|
|
StarPunk → GET https://gondulf.thesatelliteoflove.com/token
|
|
Authorization: Bearer abc123...
|
|
|
|
Gondulf → 200 OK
|
|
{
|
|
"me": "https://thesatelliteoflove.com",
|
|
"client_id": "https://starpunk.example",
|
|
"scope": "create"
|
|
}
|
|
```
|
|
|
|
### What Actually Happens
|
|
```
|
|
StarPunk → GET https://gondulf.thesatelliteoflove.com/token
|
|
Authorization: Bearer abc123...
|
|
|
|
Gondulf → 405 Method Not Allowed
|
|
(Server doesn't support GET on /token)
|
|
```
|
|
|
|
## Code Analysis
|
|
|
|
### Our Implementation (Correct)
|
|
|
|
From `/home/phil/Projects/starpunk/starpunk/auth_external.py` line 425:
|
|
|
|
```python
|
|
def _verify_with_endpoint(endpoint: str, token: str) -> Dict[str, Any]:
|
|
"""
|
|
Verify token with the discovered token endpoint
|
|
|
|
Makes GET request to endpoint with Authorization header.
|
|
"""
|
|
headers = {
|
|
'Authorization': f'Bearer {token}',
|
|
'Accept': 'application/json',
|
|
}
|
|
|
|
response = httpx.get( # ← Correct: Using GET
|
|
endpoint,
|
|
headers=headers,
|
|
timeout=VERIFICATION_TIMEOUT,
|
|
follow_redirects=True,
|
|
)
|
|
```
|
|
|
|
### IndieAuth Spec Reference
|
|
|
|
From W3C IndieAuth Section 6.3.4:
|
|
|
|
> "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."
|
|
|
|
(Emphasis added)
|
|
|
|
## Why the Provider is Wrong
|
|
|
|
The gondulf IndieAuth provider appears to:
|
|
1. Only implement POST for token issuance
|
|
2. Not implement GET for token verification
|
|
3. Return 405 for any GET requests to /token
|
|
|
|
This is only a partial implementation of IndieAuth.
|
|
|
|
## Impact Analysis
|
|
|
|
### What This Breaks
|
|
- StarPunk cannot authenticate users through gondulf
|
|
- Any other spec-compliant Micropub client would also fail
|
|
- The provider is not truly IndieAuth compliant
|
|
|
|
### What This Doesn't Break
|
|
- Our code is correct
|
|
- We can work with any compliant IndieAuth provider
|
|
- The architecture is sound
|
|
|
|
## Solutions
|
|
|
|
### Option 1: Fix the Provider (Recommended)
|
|
The gondulf provider needs to:
|
|
1. Add GET method support to /token endpoint
|
|
2. Verify bearer tokens from Authorization header
|
|
3. Return appropriate JSON response
|
|
|
|
### Option 2: Use a Different Provider
|
|
Known compliant providers:
|
|
- IndieAuth.com
|
|
- IndieLogin.com
|
|
- Self-hosted IndieAuth servers that implement full spec
|
|
|
|
### Option 3: Work Around (Not Recommended)
|
|
We could add a non-compliant mode, but this would:
|
|
- Violate the specification
|
|
- Encourage bad implementations
|
|
- Add unnecessary complexity
|
|
- Create security concerns
|
|
|
|
## Summary
|
|
|
|
**Your Question**: "Why are we making GET requests to these endpoints?"
|
|
|
|
**Answer**: Because that's what the IndieAuth specification requires for token verification. We're doing it right. The gondulf provider is doing it wrong.
|
|
|
|
**Action Required**: The gondulf IndieAuth provider needs to implement GET support on their token endpoint to be IndieAuth compliant.
|
|
|
|
## References
|
|
|
|
1. [W3C IndieAuth - Token Verification](https://www.w3.org/TR/indieauth/#token-verification)
|
|
2. [RFC 6750 - OAuth 2.0 Bearer Token Usage](https://datatracker.ietf.org/doc/html/rfc6750)
|
|
3. [StarPunk Implementation](https://github.com/starpunk/starpunk/blob/main/starpunk/auth_external.py)
|
|
|
|
## Contact Information for Provider
|
|
|
|
If you need to report this to the gondulf provider:
|
|
|
|
"Your IndieAuth token endpoint at https://gondulf.thesatelliteoflove.com/token returns HTTP 405 Method Not Allowed for GET requests. Per the W3C IndieAuth specification Section 6.3.4, the token endpoint MUST support GET requests with Bearer authentication for token verification. Currently it appears to only support POST for token issuance." |