The auth routes were registered under /admin/* but the IndieAuth redirect_uri was configured as /auth/callback, causing 404 errors when providers redirected back after authentication. - Change auth blueprint url_prefix from "/admin" to "/auth" - Update test expectations for new auth route paths - Add ADR-022 documenting the architectural decision 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
6.8 KiB
ADR-022: Fix IndieAuth Callback Route Mismatch
Status
Proposed
Context
We have discovered a critical routing mismatch in our IndieAuth implementation that causes a 404 error when IndieAuth providers redirect back to our application.
The Problem
The auth blueprint is currently registered with url_prefix="/admin" in /starpunk/routes/auth.py line 30:
bp = Blueprint("auth", __name__, url_prefix="/admin")
This means all auth routes are actually served under /admin:
/admin/login- Login form/admin/callback- OAuth callback endpoint/admin/logout- Logout endpoint
However, in /starpunk/auth.py lines 325 and 414, the redirect_uri sent to IndieAuth providers is:
redirect_uri = f"{current_app.config['SITE_URL']}auth/callback"
This mismatch causes IndieAuth providers to redirect users to /auth/callback, which doesn't exist, resulting in a 404 error.
Current Route Structure
- Auth Blueprint (with
/adminprefix):/admin/login- Login form/admin/callback- OAuth callback/admin/logout- Logout endpoint
- Admin Blueprint (with
/adminprefix):/admin/- Dashboard/admin/new- Create note/admin/edit/<id>- Edit note/admin/delete/<id>- Delete note
Decision
Change the auth blueprint URL prefix from /admin to /auth to match the redirect_uri being sent to IndieAuth providers.
Rationale
1. Separation of Concerns
Authentication routes (/auth/*) should be semantically separate from administration routes (/admin/*). This creates a cleaner architecture where:
/auth/*handles authentication flows (login, callback, logout)/admin/*handles protected administrative functions (dashboard, CRUD operations)
2. Standards Compliance
IndieAuth and OAuth2 conventions typically use /auth/callback for OAuth callbacks:
- Most OAuth documentation and examples use this pattern
- IndieAuth implementations commonly expect callbacks at
/auth/callback - Follows RESTful URL design principles
3. Security Benefits
Clear separation provides:
- Easier application of different security policies (rate limiting on auth vs admin)
- Clearer audit trails and access logs
- Reduced cognitive load when reviewing security configurations
- Better principle of least privilege implementation
4. Minimal Impact
Analysis of the codebase shows:
- No hardcoded URLs to
/admin/loginin external-facing documentation - All internal redirects use
url_for('auth.login_form')which will automatically adjust - Templates use named routes:
url_for('auth.login_initiate'),url_for('auth.logout') - No stored auth_state data is tied to the URL path
5. Future Flexibility
If we later need public authentication for other features:
- API token generation could live at
/auth/tokens - OAuth provider functionality could use
/auth/authorize - WebAuthn endpoints could use
/auth/webauthn - All auth-related functionality stays organized under
/auth
Consequences
Positive
- Fixes the immediate bug: IndieAuth callbacks will work correctly
- Cleaner architecture: Proper separation between auth and admin concerns
- Standards alignment: Matches common OAuth/IndieAuth patterns
- No breaking changes: All internal routes use named endpoints
- Better organization: More intuitive URL structure
Negative
- Documentation updates needed: Must update docs showing
/admin/loginpaths - Potential user confusion: Users who bookmarked
/admin/loginwill get 404- Mitigation: Could add a redirect from
/admin/loginto/auth/loginfor transition period
- Mitigation: Could add a redirect from
Migration Requirements
- No database migrations required
- No session invalidation needed
- No configuration changes needed
- Simply update the blueprint registration
Alternatives Considered
Alternative 1: Change redirect_uri to /admin/callback
Rejected because:
- Mixes authentication concerns with administration in URL structure
- Goes against common OAuth/IndieAuth URL patterns
- Less intuitive - callbacks aren't "admin" functions
- Requires changes in two places in
auth.py(lines 325 and 414)
Alternative 2: Create a separate /auth blueprint just for callback
Rejected because:
- Splits related authentication logic across multiple blueprints
- More complex routing configuration
- Harder to maintain - auth logic spread across files
- Violates single responsibility principle at module level
Alternative 3: Use root-level routes (/login, /callback, /logout)
Rejected because:
- Pollutes the root namespace
- No logical grouping of related routes
- Harder to apply auth-specific middleware
- Less scalable as application grows
Alternative 4: Keep current structure and add redirect
Rejected because:
- Doesn't fix the underlying architectural issue
- Adds unnecessary HTTP redirect overhead
- Makes debugging more complex
- Band-aid solution rather than proper fix
Implementation
Required Change
Update line 30 in /home/phil/Projects/starpunk/starpunk/routes/auth.py:
# From:
bp = Blueprint("auth", __name__, url_prefix="/admin")
# To:
bp = Blueprint("auth", __name__, url_prefix="/auth")
Results
This single change will:
- Make the callback available at
/auth/callback(matching the redirect_uri) - Move login to
/auth/login - Move logout to
/auth/logout - All template references using
url_for()will automatically resolve correctly
Optional Transition Support
If desired, add temporary redirects in starpunk/routes/admin.py:
@bp.route("/login")
def old_login_redirect():
"""Temporary redirect for bookmarks"""
return redirect(url_for("auth.login_form"), 301)
Documentation Updates Required
Files to update:
/home/phil/Projects/starpunk/TECHNOLOGY-STACK-SUMMARY.md- Update route table/home/phil/Projects/starpunk/docs/design/phase-4-web-interface.md- Update route documentation/home/phil/Projects/starpunk/docs/designs/phase-5-quick-reference.md- Update admin access instructions
Testing Verification
After implementation:
- Verify
/auth/logindisplays login form - Verify
/auth/callbackaccepts IndieAuth redirects - Verify
/auth/logoutdestroys session - Verify all admin routes still require authentication
- Test full IndieAuth flow with real provider
References
- IndieAuth Specification - Section on redirect URIs
- OAuth 2.0 RFC 6749 - Section 3.1.2 on redirection endpoints
- RESTful API Design - URL naming conventions
- Current implementation:
/home/phil/Projects/starpunk/starpunk/routes/auth.py,/home/phil/Projects/starpunk/starpunk/auth.py
Document Version: 1.0 Created: 2025-11-22 Author: StarPunk Architecture Team (agent-architect) Review Required By: agent-developer before implementation