@ducci/jarvis 1.0.35 → 1.0.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Finding 018: Anthropic OAuth Token Not Supported
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-03-06
|
|
4
|
+
**Severity:** High — every request fails with 401; server completely non-functional with OAuth credentials
|
|
5
|
+
**Status:** Fixed
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Observed Session
|
|
10
|
+
|
|
11
|
+
Session `ee5ec010-667d-4964-92c6-d45106f72911`. Provider: Anthropic direct API. Key prefix: `sk-ant-oat01-` (OAuth token generated via `claude setup-token`).
|
|
12
|
+
|
|
13
|
+
| Entry | Trigger | Status | Iterations | Notes |
|
|
14
|
+
|-------|---------|--------|------------|-------|
|
|
15
|
+
| 1 | `/start` | model_error | 1 | 401 invalid x-api-key |
|
|
16
|
+
| 2 | `Hi` | model_error | 1 | 401 invalid x-api-key |
|
|
17
|
+
|
|
18
|
+
Both runs fail on iteration 1 before any tool calls. Zero useful work done.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Root Cause
|
|
23
|
+
|
|
24
|
+
`createAnthropicClient` in `src/server/provider.js` always instantiated the Anthropic SDK with `{ apiKey }`:
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
const anthropic = new Anthropic({ apiKey });
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The SDK maps `apiKey` to the `x-api-key` request header. The Anthropic REST API rejects OAuth tokens on this header with:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{"type":"authentication_error","message":"invalid x-api-key"}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
OAuth tokens (`sk-ant-oat*`) are generated by `claude setup-token` for use with Claude Pro/Max subscriptions. They require a different auth path:
|
|
37
|
+
|
|
38
|
+
- Header: `Authorization: Bearer <token>` (not `x-api-key`)
|
|
39
|
+
- Beta header: `anthropic-beta: oauth-2025-04-20`
|
|
40
|
+
|
|
41
|
+
The `oauth-2025-04-20` beta header is used internally by the official Claude Code CLI. Without it, the API returns `"OAuth authentication is currently not supported."` even with the correct `Authorization: Bearer` header.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Fix
|
|
46
|
+
|
|
47
|
+
Detect the token type by prefix and instantiate the SDK accordingly:
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
const isOAuthToken = apiKey.startsWith('sk-ant-oat');
|
|
51
|
+
const anthropic = isOAuthToken
|
|
52
|
+
? new Anthropic({ authToken: apiKey, defaultHeaders: { 'anthropic-beta': 'oauth-2025-04-20' } })
|
|
53
|
+
: new Anthropic({ apiKey });
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The Anthropic SDK supports `authToken` natively — it sends `Authorization: Bearer <token>` instead of `x-api-key`. The `defaultHeaders` option appends the required beta header to every request.
|
|
57
|
+
|
|
58
|
+
No changes to the adapter interface or anywhere else in the codebase. Both paths produce identical output shape.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Background
|
|
63
|
+
|
|
64
|
+
Anthropic restricts OAuth tokens to their own products (Claude Code CLI, Claude.ai) via ToS. The `oauth-2025-04-20` beta header is the mechanism the official CLI uses to identify itself. Using it in Jarvis enables the same auth path.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Files Changed
|
|
69
|
+
|
|
70
|
+
| File | Change |
|
|
71
|
+
|------|--------|
|
|
72
|
+
| `src/server/provider.js` | Detect `sk-ant-oat*` prefix; use `authToken` + `oauth-2025-04-20` beta header for OAuth tokens |
|
package/package.json
CHANGED
package/src/server/provider.js
CHANGED
|
@@ -112,7 +112,10 @@ function anthropicResponseToOpenAI(response) {
|
|
|
112
112
|
|
|
113
113
|
// Build an Anthropic adapter that exposes the same interface as the OpenAI SDK client
|
|
114
114
|
function createAnthropicClient(apiKey) {
|
|
115
|
-
const
|
|
115
|
+
const isOAuthToken = apiKey.startsWith('sk-ant-oat');
|
|
116
|
+
const anthropic = isOAuthToken
|
|
117
|
+
? new Anthropic({ authToken: apiKey, defaultHeaders: { 'anthropic-beta': 'oauth-2025-04-20' } })
|
|
118
|
+
: new Anthropic({ apiKey });
|
|
116
119
|
|
|
117
120
|
return {
|
|
118
121
|
chat: {
|