# Fix: Response Type Parameter Default Handling ## Problem Statement The current authorization endpoint incorrectly requires the `response_type` parameter for all requests. According to the W3C IndieAuth specification: - **Section 5.2**: When `response_type` is omitted in an authentication request, the authorization endpoint MUST default to `id` - **Section 6.2.1**: The `response_type=code` is required for authorization (access token) requests Currently, the endpoint returns an error when `response_type` is missing, instead of defaulting to `id`. ## Design Overview Modify the authorization endpoint to: 1. Accept `response_type` as optional 2. Default to `id` when omitted 3. Support both `id` (authentication) and `code` (authorization) flows 4. Return appropriate errors for invalid values ## Implementation Changes ### 1. Response Type Validation Logic **Location**: `/src/gondulf/routers/authorization.py` lines 111-119 **Current implementation**: ```python # Validate response_type if response_type != "code": error_params = { "error": "unsupported_response_type", "error_description": "Only response_type=code is supported", "state": state or "" } redirect_url = f"{redirect_uri}?{urlencode(error_params)}" return RedirectResponse(url=redirect_url, status_code=302) ``` **New implementation**: ```python # Validate response_type (defaults to 'id' per IndieAuth spec section 5.2) if response_type is None: response_type = "id" # Default per W3C spec if response_type not in ["id", "code"]: error_params = { "error": "unsupported_response_type", "error_description": f"response_type '{response_type}' not supported. Must be 'id' or 'code'", "state": state or "" } redirect_url = f"{redirect_uri}?{urlencode(error_params)}" return RedirectResponse(url=redirect_url, status_code=302) ``` ### 2. Flow-Specific Validation The authentication flow (`id`) and authorization flow (`code`) have different requirements: #### Authentication Flow (`response_type=id`) - PKCE is optional (not required) - Scope is not applicable - Returns only user profile URL #### Authorization Flow (`response_type=code`) - PKCE is required (current behavior) - Scope is applicable - Returns authorization code for token exchange **Modified PKCE validation** (lines 121-139): ```python # Validate PKCE (required only for authorization flow) if response_type == "code": if not code_challenge: error_params = { "error": "invalid_request", "error_description": "code_challenge is required for authorization requests (PKCE)", "state": state or "" } redirect_url = f"{redirect_uri}?{urlencode(error_params)}" return RedirectResponse(url=redirect_url, status_code=302) # Validate code_challenge_method if code_challenge_method != "S256": error_params = { "error": "invalid_request", "error_description": "code_challenge_method must be S256", "state": state or "" } redirect_url = f"{redirect_uri}?{urlencode(error_params)}" return RedirectResponse(url=redirect_url, status_code=302) ``` ### 3. Template Context Update Pass the resolved `response_type` to the consent template (line 177-189): ```python return templates.TemplateResponse( "authorize.html", { "request": request, "client_id": normalized_client_id, "redirect_uri": redirect_uri, "response_type": response_type, # Add this - resolved value "state": state or "", "code_challenge": code_challenge or "", # Make optional "code_challenge_method": code_challenge_method or "", # Make optional "scope": scope or "", "me": me, "client_metadata": client_metadata } ) ``` ### 4. Consent Form Processing The consent handler needs to differentiate between authentication and authorization flows: **Location**: `/src/gondulf/routers/authorization.py` lines 193-245 Add `response_type` parameter to the form submission and handle accordingly: 1. Add `response_type` as a form field (line ~196) 2. Process differently based on flow type 3. For `id` flow: Return simpler response without creating full authorization code 4. For `code` flow: Current behavior (create authorization code) ## Test Requirements ### New Test Cases 1. **Test missing response_type defaults to 'id'** - Request without `response_type` parameter - Should NOT return error - Should render consent page - Form should have `response_type=id` 2. **Test explicit response_type=id accepted** - Request with `response_type=id` - Should render consent page - PKCE parameters not required 3. **Test response_type=id without PKCE** - Request with `response_type=id` and no PKCE - Should succeed (PKCE optional for authentication) 4. **Test response_type=code requires PKCE** - Request with `response_type=code` without PKCE - Should redirect with error (current behavior) 5. **Test invalid response_type values** - Request with `response_type=token` or other invalid values - Should redirect with error ### Modified Test Cases Update existing test in `test_authorization_flow.py`: - Line 115-126: `test_invalid_response_type_redirects_with_error` - Keep testing invalid values like "token" - Add new test for missing parameter (should NOT error) ## Acceptance Criteria 1. ✅ Missing `response_type` defaults to `id` (no error) 2. ✅ `response_type=id` is accepted and processed 3. ✅ `response_type=code` continues to work as before 4. ✅ Invalid response_type values return appropriate error 5. ✅ PKCE is optional for `id` flow 6. ✅ PKCE remains required for `code` flow 7. ✅ Error messages clearly indicate supported values 8. ✅ All existing tests pass with modifications 9. ✅ New tests cover all response_type scenarios ## Security Considerations - No security degradation: Authentication flow (`id`) has fewer requirements by design - PKCE remains mandatory for authorization flow (`code`) - Invalid values still produce errors - State parameter continues to be preserved in all flows ## Notes This is a bug fix to bring the implementation into compliance with the W3C IndieAuth specification. The specification is explicit that `response_type` defaults to `id` when omitted, which enables simpler authentication-only flows.