Tencent/WeKnora · error

cannot verify OIDC id_token: client_id is not configured

Error message

cannot verify OIDC id_token: client_id is not configured

What it means

id_token audience validation requires cfg.ClientID: the service checks the token's aud claim against the configured client_id. Without it, tokens cannot be confirmed as intended for this application, so verification fails immediately.

Source

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

	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)
	}

	claims := jwt.MapClaims{}
	if _, err := jwt.NewParser(
		jwt.WithValidMethods([]string{"RS256", "RS384", "RS512"}),

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Set ClientID in the OIDC config to the client identifier registered with the provider.
  2. Verify the env/config key mapping (e.g. OIDC_CLIENT_ID) is populated in the deployment environment.
  3. Cross-check the provider's client registration so client_id matches the one minting the tokens.
  4. Add startup validation that fails fast when required OIDC config fields are empty.

Example fix

// before
client_id: ""
// after
client_id: "my-app-client"
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(cfg.ClientID) == "" {
    return errors.New("oidc client_id is required for audience validation")
}

Type guard

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

Prevention

When it happens

Trigger: OIDCAuthConfig reaching verifyOIDCIDToken has empty/whitespace ClientID; LoginWithOIDC called with a partially filled config (JwksURI/IssuerURL set but client_id missing).

Common situations: Client secret configured but client_id left blank (or vice versa); renamed env vars not mapped to the client_id field; new OIDC provider onboarded with an incomplete config; secret-manager injected only the secret.

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/d9c7777458403453. Report an issue: GitHub.