siyuan-note/siyuan · error

OIDC authorization code is missing

Error message

OIDC authorization code is missing

What it means

finishOIDCExchange was invoked with an empty authorization code. The IdP is supposed to redirect with ?code=...; an absent code usually means the IdP sent an error/error_description instead, or the wrong redirect URI was used so the code was dropped.

Source

Thrown at kernel/model/oidc.go:903

	if err := authenticateOIDCSession(c, transaction.RememberMe); err != nil {
		writeOIDCCallbackPage(c, false, oidcUserMessage())
		return
	}
	c.Redirect(http.StatusFound, safeOIDCRedirectTarget(transaction.To))
}

func cleanupOIDCTransactionsLocked() {
	now := time.Now()
	for state, transaction := range oidcTransactions.byState {
		if now.After(transaction.ExpiresAt) {
			deleteOIDCTransactionLocked(state)
		}
	}
}

func finishOIDCExchange(c *gin.Context, transaction *oidcTransaction, code string) error {
	if code == "" {
		return errors.New("OIDC authorization code is missing")
	}
	config := Conf.GetOIDC()
	provider := transaction.Provider
	if transaction.Flow == oidcFlowValidate {
		if transaction.Config == nil || provider == nil {
			return errors.New("OIDC validation configuration is missing")
		}
		config = transaction.Config
	} else {
		var err error
		provider, err = getOIDCProvider(c.Request.Context(), transaction.RedirectURL)
		if err != nil {
			return err
		}
	}
	exchangeContext, cancel := context.WithTimeout(c.Request.Context(), oidcExchangeTimeout)
	defer cancel()
	claims, err := provider.Exchange(exchangeContext, code, transaction.CodeVerifier, transaction.Nonce)

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Check the IdP's redirect URI list contains exactly the configured public URL (https://<host>/api/system/oidc/callback).
  2. Inspect the full callback URL the IdP produced - look for error=/error_description= and address the IdP-side cause.
  3. Restart the flow and complete consent.
Defensive patterns

Strategy: validation

Validate before calling

// Surface IdP errors clearly before the kernel's generic 'code missing'.
if c.Query("error") != "" {
    return fmt.Errorf("IdP returned error: %s (%s)", c.Query("error"), c.Query("error_description"))
}
if c.Query("code") == "" {
    return errors.New("IdP callback missing authorization code")
}

Prevention

When it happens

Trigger: IdP redirects to /api/system/oidc/callback with no code parameter (commonly with ?error=...); client forwards a callback that lost the code; user denied consent at the IdP.

Common situations: Redirect URI mismatch at the IdP (IdP rejects and returns an error); IdP scope/client misconfiguration; user clicked Deny on the consent screen.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/4d1671d82043b58d. Report an issue: GitHub.