Skip to content

feat(server): forward inbound Anthropic auth - #372

Open
elyasmnvidian wants to merge 2 commits into
mainfrom
emehtabuddin/forward-anthropic-auth
Open

feat(server): forward inbound Anthropic auth#372
elyasmnvidian wants to merge 2 commits into
mainfrom
emehtabuddin/forward-anthropic-auth

Conversation

@elyasmnvidian

@elyasmnvidian elyasmnvidian commented Aug 11, 2026

Copy link
Copy Markdown
Contributor
schema_version = 1

[llm_clients.claude]
format = "anthropic_messages"
base_url = "https://api.anthropic.com"

[targets.claude]
id = "claude-opus"
llm_client = "claude"

[routes.claude]
id = "switchyard/claude"
type = "passthrough"
target = "claude"

When Claude Code sends an Authorization header or x-api-key to POST /v1/messages, current main does not copy that header to the Anthropic request. A local upstream server recorded:

{"authorization_forwarded": false}

Fix

Add forward_auth = true to the Anthropic client:

[llm_clients.claude]
format = "anthropic_messages"
base_url = "https://api.anthropic.com"
forward_auth = true

With the setting enabled, Switchyard copies the caller's Authorization or x-api-key header to the Anthropic request. For Claude subscription sign-in, it also copies oauth-* entries from anthropic-beta. Other caller-supplied beta entries still do not reach the upstream server.

forward_auth defaults to false, so configs that omit it do not start copying request credentials. The server accepts it only for anthropic_messages clients. It rejects configs that also set api_key_env or put Authorization or x-api-key in extra_headers, because those settings would give Switchyard two sources for the same credential.

Proof

I pointed Claude Code at the branch server and sent a dummy bearer token to a local Anthropic-compatible server. The local server returned HTTP 200 only when it received that bearer token:

result: SWITCHYARD_AUTH_OK
authorization_forwarded: true
anthropic_version_set: true

origin/main at 224287bc sent the same dummy bearer request without an Authorization header:

authorization_forwarded: false

Live external test

I also ran Claude Code through the branch server to an external Anthropic Messages endpoint. Claude Code returned:

SWITCHYARD_LIVE_OK

GET /v1/stats recorded one request and no errors:

total_requests: 1
errors: 0

The API key was supplied through an environment variable and sent as a bearer token. Its value does not appear in the config, command output, server stats, or this PR description.

This run checks live bearer-token forwarding. It does not check Claude subscription OAuth because Claude Code was not signed in to a subscription on this machine. The local test above checks the oauth-* beta header with a dummy token.

Tests

anthropic_client_forwards_inbound_auth_when_configured sends two requests through Switchyard's /v1/messages router to a local Anthropic server. It checks both Authorization and x-api-key, checks the required anthropic-version header, and checks that only the oauth-* beta entry reaches the upstream server.

forward_auth_rejects_unsupported_configurations checks the three rejected config combinations described above.

cargo test -p switchyard-llm-client -p switchyard-server

Closes #164

@elyasmnvidian
elyasmnvidian requested a review from a team as a code owner August 11, 2026 20:38
@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1

🚀 View preview at
https://NVIDIA-NeMo.github.io/Switchyard/pr-preview/pr-372/

Built to branch gh-pages at 2026-08-13 18:03 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The change adds forward_auth for Anthropic clients. It forwards caller credentials and selected OAuth beta markers, validates incompatible configuration, adds integration coverage, and documents the setting.

Changes

Anthropic authentication forwarding

Layer / File(s) Summary
Client authentication forwarding
crates/libsy-llm-client/src/backend.rs, crates/libsy-llm-client/src/client.rs
Adds forward_auth and conditionally forwards authorization, x-api-key, and oauth-* Anthropic beta markers.
Server configuration and validation
crates/switchyard-server/src/config.rs
Adds the setting, validates supported combinations, and passes it to HttpBackendConfig.
End-to-end forwarding tests
crates/switchyard-server/tests/server.rs
Adds an authenticated Anthropic mock endpoint and tests OAuth and API-key forwarding.
Configuration documentation
crates/libsy-llm-client/README.md, crates/switchyard-server/README.md, docs/getting_started.md, docs/reference/toml_schema.md
Documents the setting, default behavior, supported credentials, and incompatible options.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Poem

I’m a small rabbit guarding the gate,
OAuth and API keys now travel straight.
Beta markers shed what should not stay,
Tests watch each credential on its way.
Hop, hop—Anthropic calls obey!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes implement inbound Anthropic credential forwarding, OAuth marker filtering, validation, documentation, and regression coverage requested by issue #164.
Out of Scope Changes check ✅ Passed The code, tests, and documentation changes directly support the requested Anthropic authentication forwarding feature.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: forwarding inbound Anthropic authentication through the server.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/libsy-llm-client/README.md`:
- Around line 216-220: Update the HttpBackendConfig::forward_auth documentation
to explicitly scope credential and anthropic-beta forwarding behavior to
Anthropic backends, particularly anthropic_messages clients, and clarify that it
does not apply to OpenAI backends.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 40554ecd-43d1-4be7-ac4e-166ad0b5b978

📥 Commits

Reviewing files that changed from the base of the PR and between 58f355a and 4de6f1b.

📒 Files selected for processing (8)
  • crates/libsy-llm-client/README.md
  • crates/libsy-llm-client/src/backend.rs
  • crates/libsy-llm-client/src/client.rs
  • crates/switchyard-server/README.md
  • crates/switchyard-server/src/config.rs
  • crates/switchyard-server/tests/server.rs
  • docs/getting_started.md
  • docs/reference/toml_schema.md

Comment thread crates/libsy-llm-client/README.md Outdated
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
@elyasmnvidian
elyasmnvidian force-pushed the emehtabuddin/forward-anthropic-auth branch from 4de6f1b to 12b1ea1 Compare August 13, 2026 17:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] Pass through inbound Anthropic auth for anthropic-format backend

1 participant