Bring your own SSO to Claude Code.
An OAuth2 / SSO credential helper that logs Claude Code into any AI gateway
using your corporate identity —
Microsoft Entra ID, Google Workspace, or any OIDC provider. No hand-managed API keys.
When a company puts an AI gateway in front of Claude Code, it wants the credential to be the developer's SSO identity — not a shared, long-lived API key copied into a dotfile. But Claude Code speaks Anthropic-style keys, while an SSO-fronted gateway wants a short-lived OAuth bearer JWT.
ccauth bridges that gap. The developer signs in once with their company account; from then on Claude Code silently gets fresh, short-lived tokens through its apiKeyHelper hook. Access follows the IdP lifecycle (offboarding, Conditional Access, MFA), the gateway attributes usage to a real person, and no one generates or pastes an API key.
you ── ccauth login ─▶ browser SSO ─▶ refresh token stored in your OS keychain
│
Claude Code ── apiKeyHelper ─▶ ccauth token ─┤─▶ fresh short-lived token
│ · silent refresh
│ · auto browser re-auth on expiry
▼
Authorization: Bearer <jwt> + x-api-key: <jwt>
│
▼
AI gateway (validates the SSO JWT via JWKS) ─▶ Claude
- Any gateway — LiteLLM, Portkey, Bifrost, or any OIDC-aware gateway, via one tool.
- Any SSO — Entra ID, Google Workspace, or generic OIDC (Okta/Auth0/Keycloak).
- Two credential modes — passthrough (emit the raw SSO JWT for the gateway to validate) or exchange (trade it for a gateway-native key via RFC 8693 or a broker).
- Invisible refresh — the
apiKeyHelperreturns cached tokens instantly, refreshes silently, and opens a browser itself when the session finally expires — you never leave Claude Code. - Zero-config for users — IT provisions everything centrally (MDM / remote config / embedded); developers run only
ccauth login. See ENTERPRISE.md. - Secure by construction — public-client + PKCE, refresh token in the OS keychain, tokens never logged.
Deep dive: architecture, the gateway compatibility matrix, and the research behind each decision live in DESIGN.md.
# from source (Go 1.25+)
git clone https://github.com/PalenaAI/claude-code-auth-helper.git
cd claude-code-auth-helper
make install # builds ./ccauth into $GOBIN (or `make build` for ./ccauth)Prebuilt, checksummed static binaries for macOS/Linux/Windows: make package → dist/.
ccauth setup --write # pick provider + gateway; writes config + Claude Code wiring
ccauth login # sign in (browser). Use --device for headless/SSH.
ccauth status # confirm you're logged in and see token expiry
# start Claude Code — it now authenticates through your SSOPrefer to hand-edit? ccauth init writes a fully commented config; ccauth wire prints the exact settings.json block.
| Command | What it does |
|---|---|
ccauth setup [--write] |
Interactive wizard: choose provider + gateway, write the profile (and optionally the Claude Code wiring) |
ccauth init [--force] |
Write a commented example config.toml to edit by hand |
ccauth login [--device] |
Interactive SSO sign-in; stores the refresh token in your OS keychain |
ccauth token |
Print the current credential to stdout — this is your apiKeyHelper. Silent refresh; auto browser re-auth on expiry |
ccauth status [--json] |
Show the active profile, config source, login state, and token expiry |
ccauth wire [--write] |
Print (or merge) the settings.json wiring for a profile |
ccauth config path|show|sync |
Inspect the config layers (user/embedded/managed/remote) or pull remote config |
ccauth doctor [--probe] |
Diagnose config + session and print the gateway-side checklist |
ccauth logout |
Delete the stored session for a profile |
ccauth gateways |
List supported gateways and how each authenticates |
All commands accept -p/--profile <name> (default: the config's default_profile).
Run ccauth gateways for the live table.
| Gateway | Native inbound JWT? | Mode | Notes |
|---|---|---|---|
| LiteLLM (Enterprise) | ✅ enable_jwt_auth (+ OAuth2 introspection) |
passthrough | Set JWT_AUDIENCE + JWT_ISSUER — unset = checks silently off. example |
| Portkey (Enterprise) | ✅ JWKS, RS256, org mapping | passthrough | Base URL https://api.portkey.ai (no /v1). example |
| Bifrost | ❌ virtual-key only | exchange | Broker → sk-bf-*, or the edge-auth plugin |
| Generic OIDC gateway | ✅ (you configure JWKS) | passthrough | Envoy / APISIX / Kong / custom |
Config lives at ~/.config/ccauth/config.toml (override with CCAUTH_CONFIG_DIR), one [profiles.<name>] per gateway+SSO combination. Minimal Entra → LiteLLM:
default_profile = "work"
[profiles.work]
provider = "entra"
gateway = "litellm"
mode = "passthrough"
[profiles.work.oauth]
tenant_id = "<tenant-guid>"
client_id = "<app-registration-client-id>"
scopes = ["api://<gateway-app-id>/.default"]
flow = "auth_code" # or "device_code"
[profiles.work.gateway_opts]
base_url = "http://localhost:4000"
ttl_ms = 3000000ccauth init documents every provider/gateway combination. Env overrides for CI/headless: CCAUTH_TENANT_ID, CCAUTH_CLIENT_ID, CCAUTH_CLIENT_SECRET, CCAUTH_ISSUER, CCAUTH_BASE_URL.
Setting up your identity provider? Step-by-step guides (provider app + the matching gateway validation values): Microsoft Entra ID · Google Workspace · Keycloak / generic OIDC.
Users shouldn't type tenant/client IDs or run a wizard. IT provisions everything centrally and the developer runs only ccauth login (or nothing — the helper opens the browser when needed). Config is layered (user < embedded < managed < remote), distributable via MDM managed file, remote config URL, or a compile-time embedded branded binary, with an optional allow_user_profiles = false lockdown.
Full guide: ENTERPRISE.md.
ccauth config path # which layers are active on this machine
ccauth config show # merged config + per-profile source (secrets redacted)- Public client + PKCE + loopback redirect (no client secret on disk for Entra/OIDC public clients).
- Refresh token in the OS keychain, with a
0600-file fallback for headless environments. - Only short-lived tokens are emitted; ccauth never logs tokens.
- The gateway verifies signature +
iss+aud+exp+ scopes; ccauth reads token expiry unverified only to time refreshes. - Report vulnerabilities per SECURITY.md — not via public issues.
| Symptom | Likely cause / fix |
|---|---|
no valid session … run ccauth login |
Not logged in for this profile, and auto-reauth is disabled/unavailable (headless). Run ccauth login -p <name>. |
Gateway returns 401 |
Wrong mode, or the gateway isn't validating your IdP. Run ccauth doctor and check the gateway-side checklist (JWT_AUDIENCE/JWT_ISSUER on LiteLLM, JWKS registration on Portkey). |
OIDC discovery … failed |
Bad issuer/tenant. Entra needs a tenant GUID or verified domain, not common. |
| Google re-prompts weekly | Publish the OAuth consent screen — "Testing" apps get 7-day refresh tokens. |
| Device flow blocked (Entra) | Conditional Access may block device-code. Use flow = "auth_code". |
Run ccauth doctor --probe to exercise the whole path end-to-end (credential redacted).
make build # ./ccauth
make test # unit tests (race)
make vet
make license-check # verify Apache headers
make package # dist/ cross-compiled binaries + LICENSE/NOTICE + SHA256SUMSContributions welcome — see CONTRIBUTING.md (CLA + DCO sign-off required).
Licensed under the Apache License, Version 2.0 — Copyright 2026 bitkaio LLC (https://bitkaio.com). See LICENSE and NOTICE.
The Claude mark is a trademark of Anthropic PBC, used nominatively to indicate compatibility. Not affiliated with Anthropic, LiteLLM, Portkey, or Bifrost.