anthropic auth proxy for multi-user claude code
Local HTTP proxy on 127.0.0.1:5051 intercepts Claude Code API requests from sandboxed member users, injects the real OAuth token server-side, and forwards to Anthropic. Users only see a proxy secret, never the real credentials. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
import { join } from 'node:path';
|
||||
import { existsSync } from 'node:fs';
|
||||
import {
|
||||
getHomeDir,
|
||||
DATA_PATH,
|
||||
getNativeToolsDir,
|
||||
getGlobalToolsDir,
|
||||
getUserToolsDir,
|
||||
@@ -15,9 +13,11 @@ import { readToolDirs, parseFrontmatter as parseToolFrontmatter } from '@@/api/t
|
||||
import { readSkillDirs, parseFrontmatter as parseSkillFrontmatter } from '@@/api/skills/skills';
|
||||
import { buildHostToolEnv } from '@@/api/pi/pi-bridge';
|
||||
import { logger } from '@@/api/pi/logger';
|
||||
import { proxySecret } from '@@/api/anthropic-proxy';
|
||||
import type { MessageCost, PiEvent } from '@@/api/pi/types';
|
||||
|
||||
const SEND_TIMEOUT_MS = 5 * 60 * 1000;
|
||||
const PROXY_PORT = process.env.ANTHROPIC_PROXY_PORT ?? '5051';
|
||||
|
||||
// Resolve absolute path to claude binary so sudo -u can find it regardless of target user's PATH
|
||||
const CLAUDE_BIN = (() => {
|
||||
@@ -162,10 +162,13 @@ export async function sendClaudeCode(params: ClaudeCodeParams): Promise<ClaudeCo
|
||||
|
||||
const isServiceUser = shellUsername === (process.env.USER ?? '');
|
||||
|
||||
// For service user, keep real HOME so Claude Code finds its credentials
|
||||
// For service user, keep real HOME so Claude Code finds its credentials.
|
||||
// For other users, route through the local Anthropic proxy.
|
||||
const env: Record<string, string> = {
|
||||
...toolEnv,
|
||||
...(isServiceUser ? { HOME: process.env.HOME ?? '' } : {}),
|
||||
...(isServiceUser
|
||||
? { HOME: process.env.HOME ?? '' }
|
||||
: { ANTHROPIC_BASE_URL: `http://127.0.0.1:${PROXY_PORT}`, ANTHROPIC_API_KEY: proxySecret }),
|
||||
PATH: process.env.PATH ?? '',
|
||||
TERM: 'xterm-256color',
|
||||
};
|
||||
@@ -317,10 +320,13 @@ export async function sendClaudeCodeStreaming(params: ClaudeCodeStreamingParams)
|
||||
|
||||
const isServiceUser = shellUsername === (process.env.USER ?? '');
|
||||
|
||||
// For service user, keep real HOME so Claude Code finds its credentials
|
||||
// For service user, keep real HOME so Claude Code finds its credentials.
|
||||
// For other users, route through the local Anthropic proxy.
|
||||
const env: Record<string, string> = {
|
||||
...toolEnv,
|
||||
...(isServiceUser ? { HOME: cleanEnv.HOME ?? '' } : {}),
|
||||
...(isServiceUser
|
||||
? { HOME: cleanEnv.HOME ?? '' }
|
||||
: { ANTHROPIC_BASE_URL: `http://127.0.0.1:${PROXY_PORT}`, ANTHROPIC_API_KEY: proxySecret }),
|
||||
PATH: cleanEnv.PATH ?? '',
|
||||
TERM: 'xterm-256color',
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user