BREAKING: Removes INDIELOGIN_URL config - endpoints are now properly discovered from user's profile URL as required by W3C IndieAuth spec. - auth.py: Uses discover_endpoints() to find authorization_endpoint - config.py: Deprecation warning for obsolete INDIELOGIN_URL setting - auth_external.py: Relaxed validation (allows auth-only flows) - tests: Updated to mock endpoint discovery This fixes a regression where admin login was hardcoded to use indielogin.com instead of respecting the user's declared endpoints. Version: 1.5.0-hotfix.1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
7.8 KiB
IndieAuth Endpoint Discovery Hotfix - Implementation Report
Date: 2025-12-17 Type: Production Hotfix Priority: Critical Status: Implementation Complete
Summary
Successfully implemented the IndieAuth endpoint discovery hotfix as specified in the design document. The authentication flow now correctly discovers endpoints from the user's profile URL per the W3C IndieAuth specification, instead of hardcoding the indielogin.com service.
Implementation Steps
All implementation steps were completed successfully:
Step 1: Update starpunk/config.py - Remove INDIELOGIN_URL
- Removed
INDIELOGIN_URLconfig line (previously line 37) - Added deprecation warning for users still setting
INDIELOGIN_URLin environment - Warning directs users to remove the deprecated config
Step 2: Update starpunk/auth.py - Add imports and use endpoint discovery
- Added imports:
discover_endpoints,DiscoveryError,normalize_urlfromstarpunk.auth_external - Rewrote
initiate_login():- Now discovers authorization_endpoint from the user's profile URL
- Uses discovered endpoint instead of hardcoded INDIELOGIN_URL
- Raises DiscoveryError if endpoint discovery fails or no authorization_endpoint found
- Rewrote
handle_callback():- Discovers authorization_endpoint from ADMIN_ME profile
- Uses authorization_endpoint for authentication-only flow (per IndieAuth spec)
- Does NOT include
grant_typeparameter (not needed for auth-only flows) - Uses
normalize_url()for URL comparison to handle trailing slashes and case differences
Step 3: Update starpunk/auth_external.py - Relax endpoint validation
- Changed endpoint validation in
_fetch_and_parse():- Now requires at least one endpoint (authorization_endpoint OR token_endpoint)
- Previously required token_endpoint to be present
- This allows profiles with only authorization_endpoint to work for login
- Micropub will still require token_endpoint and fail gracefully with 401
Step 4: Update starpunk/routes/auth.py - Import and handle DiscoveryError
- Added import for
DiscoveryErrorfromstarpunk.auth_external - Added exception handler in
login_initiate():- Catches DiscoveryError
- Logs technical details at ERROR level
- Shows user-friendly message: "Unable to verify your profile URL. Please check that it's correct and try again."
- Redirects back to login form
Step 5: Update tests/test_auth.py - Mock discover_endpoints()
- Removed
INDIELOGIN_URLfrom test app fixture - Updated all tests that call
initiate_login()orhandle_callback():- Added
@patch("starpunk.auth.discover_endpoints")decorator - Mock returns both authorization_endpoint and token_endpoint
- Updated assertions to check for discovered endpoint instead of indielogin.com
- Added
- Tests updated:
TestInitiateLogin.test_initiate_login_successTestInitiateLogin.test_initiate_login_stores_stateTestHandleCallback.test_handle_callback_successTestHandleCallback.test_handle_callback_unauthorized_userTestHandleCallback.test_handle_callback_indielogin_errorTestHandleCallback.test_handle_callback_no_identityTestLoggingIntegration.test_initiate_login_logs_at_debugTestLoggingIntegration.test_initiate_login_info_levelTestLoggingIntegration.test_handle_callback_logs_http_details
Step 6: Update tests/test_auth_external.py - Fix error message
- Updated
test_discover_endpoints_no_token_endpoint:- Changed assertion from "No token endpoint found" to "No IndieAuth endpoints found"
- Matches new relaxed validation error message
Step 7: Run tests to verify implementation
- All 51 tests in
tests/test_auth.pypass - All 35 tests in
tests/test_auth_external.pypass - All 32 tests in
tests/test_routes_admin.pypass - No regressions detected
Files Modified
| File | Lines Changed | Description |
|---|---|---|
starpunk/config.py |
9 added, 1 removed | Removed INDIELOGIN_URL, added deprecation warning |
starpunk/auth.py |
1 added, 84 replaced | Added imports, rewrote initiate_login() and handle_callback() |
starpunk/auth_external.py |
6 replaced | Relaxed endpoint validation |
starpunk/routes/auth.py |
5 added | Added DiscoveryError import and exception handling |
tests/test_auth.py |
1 removed, 43 modified | Removed INDIELOGIN_URL from fixture, added mocks |
tests/test_auth_external.py |
2 modified | Updated error message assertion |
Key Implementation Details
Authorization Endpoint Usage
Per IndieAuth spec and architect clarifications:
- Authentication-only flows POST to the authorization_endpoint (not token_endpoint)
- The
grant_typeparameter is NOT included (only for access token flows) - This differs from the previous implementation which incorrectly used indielogin.com's endpoints
URL Normalization
The implementation now uses normalize_url() when comparing the returned 'me' URL with ADMIN_ME:
- Handles trailing slash differences (https://example.com vs https://example.com/)
- Handles case differences (https://Example.com vs https://example.com)
- This is spec-compliant behavior that was previously missing
Error Handling
- Discovery failures are caught and logged at ERROR level
- User-facing error message is simplified and friendly
- Technical details remain in logs for debugging
Backward Compatibility
- Deprecation warning added for INDIELOGIN_URL environment variable
- Existing .env files with INDIELOGIN_URL will log a warning but continue to work
- Users are instructed to remove the deprecated config
Testing Results
Unit Tests
tests/test_auth.py: 51/51 passedtests/test_auth_external.py: 35/35 passedtests/test_routes_admin.py: 32/32 passed
Integration
All modified tests now correctly mock endpoint discovery and validate the new behavior.
Issues Encountered
No significant issues encountered during implementation. The design document was thorough and all architect clarifications were addressed:
- Import placement - Moved to top-level as specified
- URL normalization - Included as intentional bugfix
- Endpoint selection - Used authorization_endpoint for auth-only flows
- Validation relaxation - Allowed profiles with only authorization_endpoint
- Test strategy - Mocked discover_endpoints() and removed INDIELOGIN_URL
- grant_type parameter - Correctly omitted for auth-only flows
- Error messages - Simplified user-facing messages
Next Steps
-
Manual testing recommended:
- Test login flow with actual IndieAuth profile
- Verify endpoint discovery logs appear
- Test with profiles that have custom endpoints
- Verify error message appears for profiles without endpoints
-
Deployment:
- Update production .env to remove INDIELOGIN_URL (optional - will show warning)
- Deploy changes
- Monitor logs for "Discovered authorization_endpoint" messages
- Verify login works for admin user
-
Documentation:
- Update CHANGELOG.md with hotfix entry
- Consider adding migration guide if needed
Verification Checklist
- All specified files modified
- All code changes follow architect's design exactly
- Tests updated and passing
- Error messages user-friendly
- Logging appropriate for debugging
- URL normalization implemented
- Endpoint validation relaxed correctly
- No regressions in existing tests
- Implementation report created
Conclusion
The hotfix has been successfully implemented according to the architect's design. The authentication flow now correctly implements the W3C IndieAuth specification for endpoint discovery. All tests pass and no regressions were detected.
The critical production bug preventing user login should be resolved once this code is deployed.
Developer: Claude (Fullstack Developer Subagent) Date Completed: 2025-12-17 Ready for Review: Yes