siyuan-note/siyuan · error

OIDC issuer URL is required

Error message

OIDC issuer URL is required

What it means

For Custom and Microsoft providers, discovery starts from the issuer URL, so ValidateOIDCConfiguration requires config.IssuerURL to be non-empty for those providers. Missing it fails validation with "OIDC issuer URL is required" before any HTTP request is attempted.

Solutions

  1. Set the provider's issuer URL (base issuer, typically no /well-known suffix) in the OIDC settings, e.g. https://accounts.example.com.
  2. For Microsoft use the tenant-specific issuer such as https://login.microsoftonline.com/<tenant>/v2.0.
  3. Confirm the URL serves the OpenID discovery document at <issuer>/.well-known/openid-configuration.
  4. Re-save settings and rerun validation to confirm the error is gone.

Example fix

// before
config := &conf.OIDC{Enabled: true, Provider: conf.OIDCProviderCustom, ClientID: "app"}
// after
config := &conf.OIDC{Enabled: true, Provider: conf.OIDCProviderCustom, ClientID: "app", IssuerURL: "https://id.example.com"}
Defensive patterns

Strategy: validation

Validate before calling

// Go: require issuer for custom/microsoft providers before login
if (cfg.Provider == conf.OIDCProviderCustom || cfg.Provider == conf.OIDCProviderMicrosoft) && cfg.IssuerURL == "" {
	return errors.New("set the issuer URL (e.g. https://id.example.com) for this provider")
}

Type guard

func hasIssuer(cfg *conf.OIDC) bool {
	if cfg == nil { return false }
	switch cfg.Provider {
	case conf.OIDCProviderCustom, conf.OIDCProviderMicrosoft:
		return strings.TrimSpace(cfg.IssuerURL) != ""
	default:
		return true
	}
}

Try / catch

// JavaScript caller
try {
  await startOIDCLogin();
} catch (e) {
  if (e.msg.includes("issuer URL is required")) {
    focusField("oidcIssuerURL");
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling ValidateOIDCConfiguration with Provider == OIDCProviderCustom or OIDCProviderMicrosoft and IssuerURL == "" — e.g. selecting a custom provider, enabling OIDC, and filling only client ID/secret.

Common situations: Switching from GitHub (which needs no issuer URL) to a custom provider without adding one; forgetting the issuer endpoint of an internal Keycloak/Authentik/Dex deployment; mobile config that copied only the client credentials.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/10d06a96ca18f3c8. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/oidc.go:466

	return
}

func validateOIDCConfiguration() error {
	return ValidateOIDCConfiguration(Conf.GetOIDC())
}

func ValidateOIDCConfiguration(config *conf.OIDC) error {
	if config == nil || !config.Enabled {
		return errors.New("OIDC login is not enabled")
	}
	if config.ClientID == "" {
		return errors.New("OIDC client ID is required")
	}
	if config.Provider == conf.OIDCProviderGitHub && config.ClientSecret == "" {
		return errors.New("GitHub OAuth client secret is required")
	}
	if (config.Provider == conf.OIDCProviderCustom || config.Provider == conf.OIDCProviderMicrosoft) && config.IssuerURL == "" {
		return errors.New("OIDC issuer URL is required")
	}
	if (config.Provider == conf.OIDCProviderCustom || config.Provider == conf.OIDCProviderMicrosoft) && config.IssuerURL != "" {
		issuer, err := url.Parse(config.IssuerURL)
		if err != nil || issuer.Host == "" || issuer.User != nil || issuer.RawQuery != "" || issuer.Fragment != "" ||
			(issuer.Scheme != "https" && !util.IsLocalHostname(issuer.Hostname())) {
			return errors.New("OIDC issuer URL must use HTTPS unless it is a loopback address")
		}
	}
	if config.Provider != conf.OIDCProviderCustom && config.Provider != conf.OIDCProviderGoogle &&
		config.Provider != conf.OIDCProviderMicrosoft && config.Provider != conf.OIDCProviderGitHub {
		return errors.New("Unsupported OIDC provider")
	}
	if !config.AllowAll && len(config.ClaimRules) == 0 {
		return errors.New("OIDC login requires at least one claim rule when Allow all users is disabled")
	}
	for _, rule := range config.ClaimRules {
		if rule == nil || rule.Claim == "" || len(rule.Values) == 0 {
			return errors.New("OIDC claim rules must include a claim and at least one value")

View on GitHub (pinned to 9f775e8a12)