siyuan-note/siyuan · error

GitHub OAuth client secret is required

Error message

GitHub OAuth client secret is required

What it means

New refuses to construct a GitHub OIDC/OAuth provider when config.Provider is conf.OIDCProviderGitHub and config.ClientSecret is empty. GitHub's OAuth app flow requires the client secret during the token exchange, so a Provider without one can never complete sign-in. The error is raised eagerly at provider construction to surface the misconfiguration immediately.

Solutions

  1. Enter the GitHub OAuth app's Client Secret in the OIDC settings and save.
  2. If the secret is injected from the environment, verify the env var is set in the process environment before the kernel starts.
  3. Create a new OAuth App on GitHub (Developer settings) and copy the secret if the old one was lost or revoked.
  4. Restart the sign-in flow after saving so New is called with the complete config.

Example fix

// before
cfg := &conf.OIDC{Provider: conf.OIDCProviderGitHub, ClientID: "Iv1.xxxx"} // no secret
provider, err := New(cfg, redirectURL)
// after
cfg := &conf.OIDC{Provider: conf.OIDCProviderGitHub, ClientID: "Iv1.xxxx", ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET")}
if cfg.ClientSecret == "" {
    return errors.New("GITHUB_CLIENT_SECRET is not set")
}
provider, err := New(cfg, redirectURL)
Defensive patterns

Strategy: validation

Validate before calling

if cfg.Provider == conf.OIDCProviderGitHub && strings.TrimSpace(cfg.ClientSecret) == "" {
    return errors.New("GitHub client secret must be set in OIDC settings")
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "client secret is required") {
        // prompt the admin to enter the GitHub OAuth app secret
    }
    return err
}

Prevention

When it happens

Trigger: Calling New with config.Provider == conf.OIDCProviderGitHub and config.ClientSecret == "" — e.g. the admin created the GitHub OAuth app but never copied the secret into the SiYuan OIDC settings.

Common situations: Admin pasted only the client ID from GitHub; the secret was rotated/revoked and cleared from config; config was copied between environments (staging to production) with the secret redacted; storing the secret in an env var that is unset in the deployment.

Related errors


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

Appendix: source

Thrown at kernel/model/oidc_provider/provider.go:46

type Provider struct {
	kind         string
	oauth2Config *oauth2.Config
	verifier     *oidc.IDTokenVerifier
}

func New(ctx context.Context, config *conf.OIDC, redirectURL string) (*Provider, error) {
	if config == nil {
		return nil, errors.New("OIDC configuration is missing")
	}
	if config.ClientID == "" {
		return nil, errors.New("OIDC client ID is required")
	}
	if redirectURL == "" {
		return nil, errors.New("OIDC redirect URL is required")
	}
	if config.Provider == conf.OIDCProviderGitHub && config.ClientSecret == "" {
		return nil, errors.New("GitHub OAuth client secret is required")
	}
	issuerURL := strings.TrimSpace(config.IssuerURL)
	switch config.Provider {
	case conf.OIDCProviderGoogle:
		issuerURL = googleIssuer
	case conf.OIDCProviderMicrosoft:
		// Microsoft 多租户端点的 issuer 会随租户变化,必须使用租户专属 issuer。
	case conf.OIDCProviderCustom:
	case conf.OIDCProviderGitHub:
		return newGitHub(config, redirectURL), nil
	default:
		return nil, fmt.Errorf("unsupported OIDC provider [%s]", config.Provider)
	}
	if issuerURL == "" {
		return nil, errors.New("OIDC issuer URL is required")
	}
	discovered, err := oidc.NewProvider(ctx, issuerURL)
	if err != nil {

View on GitHub (pinned to 9f775e8a12)