infiniflow/ragflow · error · ValueError

Missing issuer in configuration.

Error message

Missing issuer in configuration.

What it means

OIDCClient.__init__ treats config['issuer'] as the single source of truth for discovery and raises ValueError('Missing issuer in configuration.') (api/apps/auth/oidc.py:77) when it is absent or falsy. This fires before any network call - the OIDC client cannot be constructed without an issuer URL.

Source

Thrown at api/apps/auth/oidc.py:77

    crucially, the fallback is to RS256, **never** to whatever the JWT
    header claims at verification time.
    """
    advertised = metadata.get("id_token_signing_alg_values_supported") or []
    if not isinstance(advertised, (list, tuple)):
        advertised = []
    safe = [a for a in advertised if isinstance(a, str) and a in _ALLOWED_OIDC_SIGNING_ALGS]
    return safe or list(_DEFAULT_OIDC_SIGNING_ALGS)


class OIDCClient(OAuthClient):
    def __init__(self, config):
        """
        Initialize the OIDCClient with the provider's configuration.
        Use `issuer` as the single source of truth for configuration discovery.
        """
        self.issuer = config.get("issuer")
        if not self.issuer:
            raise ValueError("Missing issuer in configuration.")

        oidc_metadata = self._load_oidc_metadata(self.issuer)
        config.update(
            {
                "issuer": oidc_metadata["issuer"],
                "jwks_uri": oidc_metadata["jwks_uri"],
                "authorization_url": oidc_metadata["authorization_endpoint"],
                "token_url": oidc_metadata["token_endpoint"],
                "userinfo_url": oidc_metadata["userinfo_endpoint"],
            }
        )

        super().__init__(config)
        self.issuer = config["issuer"]
        self.jwks_uri = config["jwks_uri"]
        # Pin the accepted ID-token signing algorithms at construction time
        # from a trusted source (provider metadata + safe allowlist) so the
        # JWT verification step in :meth:`parse_id_token` cannot be tricked

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Add the issuer URL (the base URL of the IdP, no /.well-known suffix), e.g. "issuer": "https://accounts.google.com".
  2. Or switch type to 'oauth2' and configure authorization/token/userinfo endpoints explicitly if you cannot use discovery.
  3. If you meant GitHub login, use type 'github' instead of 'oidc'.
  4. Double-check trailing content: issuer must be the bare base URL; the code appends /.well-known/openid-configuration itself.

Example fix

// before
{"type": "oidc", "client_id": "...", "client_secret": "..."}

// after
{"type": "oidc", "issuer": "https://sso.example.com/realms/main", "client_id": "...", "client_secret": "..."}
Defensive patterns

Strategy: validation

Validate before calling

if str(config.get("type", "")).lower() in ("", "oidc"):
    issuer = config.get("issuer")
    if not issuer or not str(issuer).startswith(("http://", "https://")):
        raise ValueError("OIDC providers require a valid issuer URL")

Type guard

def has_oidc_issuer(config: dict) -> bool:
    issuer = config.get("issuer")
    return isinstance(issuer, str) and issuer.strip() != ""

Try / catch

try:
    client = OIDCClient(config)
except ValueError as e:
    if "Missing issuer" in str(e):
        raise ConfigError("Add 'issuer' to the OIDC provider configuration") from e
    raise

Prevention

When it happens

Trigger: Auth config declares type 'oidc' but omits the issuer key; issuer is set to an empty string or null; the config was written for a plain OAuth2 provider (endpoints listed individually) and the type was later changed to 'oidc' without adding issuer.

Common situations: Editing provider settings by hand; type inference surprises - an empty type WITH an issuer silently becomes 'oidc', so a half-finished config reaches OIDCClient; config migrations dropping the field.

Related errors


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/95b03543a66c1688. Report an issue: GitHub.