{"record":{"id":"4158b8b961b92090","repo":"bytedance/deer-flow","slug":"invalid-provider-id","errorCode":null,"errorMessage":"Invalid provider ID","messagePattern":"Invalid provider ID","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"backend/app/gateway/routers/auth.py","lineNumber":672,"sourceCode":"    next: str | None = None,  # noqa: A002 (shadowing built-in is intentional — this is the query param name)\n    remember_me: bool = True,\n):\n    \"\"\"Initiate OIDC login flow.\n\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","sourceCodeStart":654,"sourceCodeEnd":690,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/auth.py#L654-L690","documentation":"400 from the OIDC login initiation: the {provider} path segment does not match _OIDC_PROVIDER_KEY_RE, a strict format pattern for provider keys (lowercase alphanumeric/kebab-style identifiers). This is lexical validation only — it fires before the provider lookup, so even a configured provider with an odd-shaped key would be unreachable via this route.","triggerScenarios":"GET /api/auth/oidc/{provider}/login with a provider containing uppercase, spaces, slashes, URL-encoded characters, or other characters outside the allowed key syntax (e.g. 'My_Provider' or 'prov%20ider').","commonSituations":"Provider keys defined in config with underscores or capitals that the regex rejects; clients passing display names or issuer hostnames instead of the configured key; path-encoding mistakes.","solutions":["Use the exact provider key from auth.oidc.providers in config.yaml, in its canonical lowercase form","Rename the config key to match the allowed syntax (letters/digits/hyphens) if it currently contains other characters","URL-encode nothing extra: pass the plain key as the path segment"],"exampleFix":"# config.yaml + request — before\nproviders:\n  My_Provider: {...}\nGET /api/auth/oidc/My_Provider/login   # 400\n\n# after\nproviders:\n  my-provider: {...}\nGET /api/auth/oidc/my-provider/login   # proceeds to redirect","handlingStrategy":"validation","validationCode":"const PROVIDER_KEY_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nif (!PROVIDER_KEY_RE.test(provider)) throw new Error(`Invalid provider key: ${provider}`);","typeGuard":"function isValidProviderKey(key: string): boolean {\n  return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(key);\n}","tryCatchPattern":"try { await startOidcLogin(provider); } catch (e) { if (e.status === 400 && /Invalid provider/.test(e.message)) { correctProviderKey(); return; } throw e; }","preventionTips":["Name provider keys in config using lowercase letters, digits, and hyphens only","Pass the config key verbatim as the path segment — never display names or issuer hostnames"],"tags":["auth","http-400","oidc","validation","provider"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}