Tencent/WeKnora · error

cannot verify OIDC id_token: issuer is not configured

Error message

cannot verify OIDC id_token: issuer is not configured

What it means

verifyOIDCIDToken validates the token's iss claim against cfg.IssuerURL, so the issuer must be configured. An empty (or whitespace-only) IssuerURL makes claim validation impossible and the service rejects verification up front.

Source

Thrown at internal/application/service/user.go:1945

	if len(jwks.Keys) == 0 {
		return nil, errors.New("JWKS document contains no keys")
	}
	return &jwks, nil
}

const oidcIDTokenLeeway = 2 * time.Minute

// verifyOIDCIDToken cryptographically verifies an OIDC id_token: it checks the
// RSA signature against the provider's JWKS (matched by kid) and validates the
// issuer, audience (client_id), expiry and subject. It returns the verified claims.
func (s *userService) verifyOIDCIDToken(
	ctx context.Context, cfg *config.OIDCAuthConfig, idToken string,
) (map[string]interface{}, error) {
	if strings.TrimSpace(cfg.JwksURI) == "" {
		return nil, errors.New("cannot verify OIDC id_token: no jwks_uri configured")
	}
	if strings.TrimSpace(cfg.IssuerURL) == "" {
		return nil, errors.New("cannot verify OIDC id_token: issuer is not configured")
	}
	if strings.TrimSpace(cfg.ClientID) == "" {
		return nil, errors.New("cannot verify OIDC id_token: client_id is not configured")
	}

	jwks, err := s.fetchOIDCJWKS(ctx, cfg.JwksURI)
	if err != nil {
		return nil, err
	}

	keyFunc := func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
			return nil, fmt.Errorf("unexpected id_token signing method: %v", token.Header["alg"])
		}
		kid, _ := token.Header["kid"].(string)
		return jwks.rsaKeyForKid(kid)
	}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Set IssuerURL to the provider's issuer identifier (must exactly match the token's iss claim, including trailing slash).
  2. Copy the issuer value from the provider's .well-known/openid-configuration `issuer` field.
  3. Check env/config wiring so the issuer actually reaches OIDCAuthConfig.IssuerURL.
  4. Trim/guard config loading to fail fast with a clear message when required OIDC fields are blank.

Example fix

// before
issuer: ""
// after
issuer: "https://idp.example.com/realms/main"
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(cfg.IssuerURL) == "" {
    return errors.New("oidc issuer_url is required (must match token iss claim)")
}

Type guard

func issuerConfigured(c config.OIDCAuthConfig) bool {
    return strings.TrimSpace(c.IssuerURL) != ""
}

Prevention

When it happens

Trigger: OIDCAuthConfig passed to verifyOIDCIDToken has empty IssuerURL while JwksURI and ClientID may be set; strings.TrimSpace(cfg.IssuerURL) == "" at user.go:1945.

Common situations: Config file with an `issuer:` key left blank; env var OIDC_ISSUER unset; copy-pasted config where only client_id and jwks_uri were filled in; YAML parsing mapping the field to the wrong key.

Understand the failure class

Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/c5da77a3a53593eb. Report an issue: GitHub.