{"record":{"id":"853781beadac82d0","repo":"BerriAI/litellm","slug":"only-s256-code-challenge-method-is-supported","errorCode":null,"errorMessage":"Only S256 code_challenge_method is supported","messagePattern":"Only S256 code_challenge_method is supported","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"litellm/proxy/_experimental/mcp_server/byok_oauth_endpoints.py","lineNumber":727,"sourceCode":"    user_api_key_dict: UserAPIKeyAuth = Depends(_byok_session_auth),\n) -> RedirectResponse:\n    \"\"\"\n    Process the BYOK API-key form submission.\n\n    Stores a short-lived authorization code and redirects the client back to\n    redirect_uri with ?code=...&state=... query parameters.\n    \"\"\"\n    _purge_expired_codes()\n\n    validate_loopback_redirect_uri(redirect_uri)\n\n    # Reject new codes if the store is at capacity (prevents memory exhaustion\n    # from a burst of abandoned OAuth flows).\n    if len(_byok_auth_codes) >= _AUTH_CODES_MAX_SIZE:\n        raise HTTPException(status_code=503, detail=\"Too many pending authorization flows\")\n\n    if code_challenge_method != \"S256\":\n        raise HTTPException(status_code=400, detail=\"Only S256 code_challenge_method is supported\")\n\n    # Identity comes from the authenticated session, not the OAuth client_id\n    # form field (RFC 6749 §2.2: client_id identifies the client application,\n    # not the user). We do bind the code to the submitted client_id so the\n    # /token call must present the same value (RFC 6749 §4.1.3).\n    user_id: Final = user_api_key_dict.user_id\n    if not user_id:\n        raise HTTPException(status_code=401, detail=\"login_required\")\n\n    auth_code: Final = str(uuid.uuid4())\n    _byok_auth_codes[auth_code] = {\n        \"api_key\": api_key,\n        \"server_id\": server_id,\n        \"code_challenge\": code_challenge,\n        \"redirect_uri\": redirect_uri,\n        # RFC 6749 §4.1.3 defense-in-depth: if the authorization request\n        # declared a client_id, the token request must submit the same\n        # value. Stored even though we don't pre-register clients.","sourceCodeStart":709,"sourceCodeEnd":745,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/_experimental/mcp_server/byok_oauth_endpoints.py#L709-L745","documentation":"Raised in the BYOK OAuth POST handler during PKCE validation when a code_challenge is accompanied by a code_challenge_method other than S256 (typically 'plain'). Plain-text PKCE is deliberately unsupported because it defeats the point of the challenge; the MCP client must use the S256 (SHA-256 hashed) method.","triggerScenarios":"Thrown at litellm/proxy/_experimental/mcp_server/byok_oauth_endpoints.py:727 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Use code_challenge_method=S256 only."],"exampleFix":"code_challenge_method=S256","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}