{"record":{"id":"76021b4bc3783782","repo":"bytedance/deer-flow","slug":"unknown-sso-provider-provider","errorCode":null,"errorMessage":"Unknown SSO provider: {provider}","messagePattern":"Unknown SSO provider: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"backend/app/gateway/routers/auth.py","lineNumber":676,"sourceCode":"\n    Redirects to the OIDC provider's authorization URL with state, nonce,\n    and PKCE parameters. The ``next`` query parameter specifies where to\n    redirect after successful login (default: /workspace).\n    \"\"\"\n    from deerflow.config.app_config import get_app_config\n\n    app_config = get_app_config()\n    oidc_config = app_config.auth.oidc\n\n    if not oidc_config.enabled:\n        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=\"SSO authentication is not enabled\")\n\n    if not _OIDC_PROVIDER_KEY_RE.match(provider):\n        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=\"Invalid provider ID\")\n\n    provider_config = oidc_config.providers.get(provider)\n    if not provider_config:\n        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f\"Unknown SSO provider: {provider}\")\n\n    # Validate `next` / open redirect prevention\n    redirect_path = validate_next_param(next) or \"/workspace\"\n\n    # Resolve redirect URI\n    redirect_uri = _resolve_oidc_redirect_uri(request, provider, provider_config)\n\n    # Generate state, nonce, PKCE\n    state_value = generate_oidc_state()\n    nonce_value = generate_nonce() if provider_config.nonce_enabled else None\n    code_verifier = generate_code_verifier() if provider_config.pkce_enabled else None\n    code_challenge = compute_code_challenge(code_verifier) if code_verifier else None\n\n    # Get provider metadata via discovery\n    overrides = {\n        \"authorization_endpoint\": provider_config.authorization_endpoint,\n        \"token_endpoint\": provider_config.token_endpoint,\n        \"userinfo_endpoint\": provider_config.userinfo_endpoint,","sourceCodeStart":658,"sourceCodeEnd":694,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/auth.py#L658-L694","documentation":"Raised by the SSO login-initiation endpoint (GET /api/auth/login/{provider} style route) in backend/app/gateway/routers/auth.py:676. The provider path segment passed the regex shape check (_OIDC_PROVIDER_KEY_RE) but no entry with that key exists under auth.oidc.providers in config.yaml. It is a 400 Bad Request, deliberately distinct from the shape-based 'Invalid provider ID'.","triggerScenarios":"GET /api/auth/sso/{provider}/login (or equivalent start route) where provider is a syntactically valid key like 'okta' but auth.oidc.providers in config.yaml only defines 'google' and 'github'.","commonSituations":"Operator typo between the provider key configured in config.yaml and the one the frontend/login button requests; a provider entry removed from config but the frontend still links to it; stale browser bookmark to an old provider slug after a config rename.","solutions":["Compare the requested provider slug against the keys of auth.oidc.providers in config.yaml (top-level repo config) and fix the mismatch on whichever side is wrong","If the provider should exist, add a full entry under auth.oidc.providers with issuer, client_id, client_secret (and scopes) then restart the Gateway","If the provider was intentionally removed, update the frontend login UI / templates to stop emitting that provider link"],"exampleFix":"# config.yaml (before)\nauth:\n  oidc:\n    enabled: true\n    providers:\n      google: {issuer: \"https://accounts.google.com\", ...}\n\n# after — provider key now matches the requested slug 'okta'\nauth:\n  oidc:\n    enabled: true\n    providers:\n      google: {issuer: \"https://accounts.google.com\", ...}\n      okta: {issuer: \"https://dev-123.okta.com\", client_id: \"...\", client_secret: \"...\", scopes: [\"openid\",\"email\",\"profile\"]}","handlingStrategy":"validation","validationCode":"# Before redirecting the user, confirm the provider exists in the server's SSO config\nKNOWN_SSO_PROVIDERS = {\"google\", \"github\"}  # keep in sync with auth.oidc.providers\nif provider not in KNOWN_SSO_PROVIDERS:\n    render_login_error(f\"Unknown SSO provider: {provider}\")\nelse:\n    window.location = `/api/auth/sso/${provider}/login`","typeGuard":"const isSsoProvider = (p: string): p is SsoProvider =>\n  [\"google\", \"github\"].includes(p);","tryCatchPattern":"try { await ssoStart(provider) } catch (e) { if (e.status === 400 && /Unknown SSO provider/.test(e.detail)) showProviderConfigError(); else throw e; }","preventionTips":["Fetch the provider list from an SSO metadata/config endpoint instead of hardcoding slugs in the frontend","Treat 400 Unknown SSO provider as permanent config drift — never auto-retry the same slug","Add a config smoke test at deploy time asserting every provider the UI links to exists in auth.oidc.providers"],"tags":["sso","oidc","auth","config","http-400"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}