siyuan-note/siyuan · error

OAuth authorization server does not support dynamic client r

Error message

OAuth authorization server does not support dynamic client registration

What it means

Thrown at oauth.go:286-287 when a fresh client registration is required (no reusable registration exists) but the AS metadata has no registration_endpoint. SiYuan performs RFC 7591 dynamic client registration because the redirect URI is a per-run localhost callback; without a registration endpoint it cannot obtain a client_id.

Source

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

	if err != nil {
		return err
	}
	callbackURL := fmt.Sprintf("http://127.0.0.1:%s/api/ai/mcp/oauth/callback/%s", util.ServerPort, flowID)
	scopes := append([]string(nil), prm.ScopesSupported...)
	if len(scopes) == 0 {
		scopes = append(scopes, asm.ScopesSupported...)
	}
	for _, scope := range strings.Fields(bearerChallengeParam(challenges, "scope")) {
		if !slices.Contains(scopes, scope) {
			scopes = append(scopes, scope)
		}
	}
	registrationCredential := credential
	canReuseRegistration := hasCredential && credential.Issuer == asm.Issuer && credential.RedirectURL == callbackURL &&
		credential.ClientID != "" && !oauthClientRegistrationExpired(credential) && oauthScopesContain(credential.Scopes, scopes)
	if !canReuseRegistration {
		if asm.RegistrationEndpoint == "" {
			return fmt.Errorf("OAuth authorization server does not support dynamic client registration")
		}
		tokenAuthMethod := preferredTokenAuthMethod(asm.TokenEndpointAuthMethodsSupported)
		if len(asm.TokenEndpointAuthMethodsSupported) > 0 && tokenAuthMethod == "" {
			return fmt.Errorf("OAuth authorization server does not support a compatible token endpoint authentication method")
		}
		grantTypes := []string{"authorization_code"}
		if len(asm.GrantTypesSupported) == 0 || slices.Contains(asm.GrantTypesSupported, "refresh_token") {
			grantTypes = append(grantTypes, "refresh_token")
		}
		registration, registerErr := oauthex.RegisterClient(ctx, asm.RegistrationEndpoint, &oauthex.ClientRegistrationMetadata{
			RedirectURIs:            []string{callbackURL},
			TokenEndpointAuthMethod: tokenAuthMethod,
			GrantTypes:              grantTypes,
			ResponseTypes:           []string{"code"},
			ClientName:              "SiYuan",
			Scope:                   strings.Join(scopes, " "),
			ApplicationType:         "native",
		}, h.client)

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Enable RFC 7591 dynamic client registration on the AS and publish registration_endpoint in its metadata.
  2. If DCR is unavailable, use an AS that supports it, since SiYuan's localhost-callback model depends on per-run registration.
  3. If registration was only rejected because scopes changed, confirm the AS exposes the needed scopes in scopes_supported so the next attempt can reuse a registration.
Defensive patterns

Strategy: validation

Validate before calling

asm, err := auth.GetAuthServerMetadata(ctx, issuerURL, http.DefaultClient)
if err != nil { return err }
if asm.RegistrationEndpoint == "" {
    return fmt.Errorf("AS %s does not support RFC 7591 dynamic client registration; required by SiYuan", issuerURL)
}

Prevention

When it happens

Trigger: First-time (or post-expiry) interactive Authorize where canReuseRegistration is false AND asm.RegistrationEndpoint == ''. Reuse fails when issuer changed, redirect URL changed, client_id empty, registration expired, or scopes no longer covered.

Common situations: AS that requires pre-registered clients (no RFC 7591 support); corporate AS where DCR is disabled by policy; AS upgraded and dropped DCR; the stored credential was invalidated (e.g. secret expired) forcing re-registration.

Related errors


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