siyuan-note/siyuan · error

OAuth callback did not include an authorization code

Error message

OAuth callback did not include an authorization code

What it means

Returned at oauth.go:391-392 when the callback has no error and the state matched, but the code parameter is empty. Per OAuth2 the AS must return either an error or a code; reaching this branch means the AS issued a non-conformant redirect.

Source

Thrown at kernel/mcp/client/oauth.go:392

	var callback oauthCallbackResult
	timer := time.NewTimer(oauthAuthorizationTimeout)
	defer timer.Stop()
	select {
	case callback = <-flow.Result:
	case <-ctx.Done():
		return ctx.Err()
	case <-timer.C:
		return fmt.Errorf("OAuth authorization timed out")
	}
	if callback.Error != "" {
		return fmt.Errorf("OAuth authorization failed: %s", callback.Error)
	}
	if callback.State != state {
		return fmt.Errorf("OAuth state mismatch")
	}
	if callback.Code == "" {
		return fmt.Errorf("OAuth callback did not include an authorization code")
	}

	exchangeCtx := context.WithValue(ctx, oauth2.HTTPClient, h.client)
	token, err := config.Exchange(exchangeCtx, callback.Code,
		oauth2.VerifierOption(verifier),
		oauth2.SetAuthURLParam("resource", prm.Resource))
	if err != nil {
		return fmt.Errorf("exchange OAuth authorization code: %w", err)
	}
	if token.TokenType != "" && !strings.EqualFold(token.TokenType, "Bearer") {
		return fmt.Errorf("OAuth token endpoint returned unsupported token type %q", token.TokenType)
	}
	credential = registrationCredential
	credential.TokenAuthMethod = authMethod
	credential.AccessToken = token.AccessToken
	credential.RefreshToken = token.RefreshToken
	credential.TokenType = token.TokenType
	credential.Expiry = token.Expiry

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Inspect the actual redirect URL the AS issued to confirm it includes the code parameter.
  2. Check for proxies or middleware between the AS and SiYuan that may strip query params from the loopback callback.
  3. Report to the AS operator: a standards-compliant authorization-code redirect must include a non-empty code when no error is present.
Defensive patterns

Strategy: validation

Try / catch

// After matching state, require a non-empty code; otherwise the AS is non-conformant.
if callback.Code == "" {
    return fmt.Errorf("OAuth callback did not include an authorization code") // not retriable; report AS bug
}

Prevention

When it happens

Trigger: The AS redirected to the callback without ?error and without ?code — e.g. it sent only state, or used a non-standard parameter name, or stripped code from a malformed redirect.

Common situations: AS bug; a reverse proxy/load balancer that strips query parameters; custom login handler on the AS that constructs the redirect incorrectly; browser extension interfering with the redirect URL.

Related errors


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