Most enterprise customers are required by policy to use short-lived, identity-broker-issued bearer tokens (Microsoft Entra ID, Okta, Ping, Vault) instead of long-lived API keys. API keys are hard to rotate, hard to scope per user, hard to audit, and a frequent source of incidents when they leak into logs, CI configs, or repos.
Today the Anthropic client supports this only partially. auth_token: str | None accepts a bearer token, but the value is captured once at construction. Tokens from these brokers expire (Entra is ~1h), so any long-running process gets 401 Unauthorized and there's no clean way to refresh without subclassing or wiring a custom httpx.Auth.
Accepting a callable would let customers wire their existing identity provider directly:
class Anthropic:
def __init__(
self,
*,
auth_token: str | Callable[[], str] | None = None,
...
): ...
If it's a string, behave like today. If it's a callable, call it per request when building the Authorization header.
Why it matters for Anthropic
- Unblocks enterprise procurement. Many security and compliance reviews flag "long-lived API keys only" as a non-starter. First-class support for federated, short-lived tokens removes a checklist item.
- Reduces credential-leak blast radius. Tokens that expire in an hour are far less damaging than keys that live until someone notices.
- Matches what enterprise developers already do with peer SDKs. The
openai Python SDK accepts api_key: str | None | Callable[[], str], so this is the pattern customers already standardize on.
- Small, low-risk change. The SDK already reads
self.auth_token via a property on every request, so the wiring is mostly in place.
Workaround in use today
from typing import Callable
from anthropic import Anthropic
class AnthropicWithTokenProvider(Anthropic):
def __init__(self, *, auth_token_provider: Callable[[], str], **kwargs):
self._auth_token_provider = auth_token_provider
super().__init__(auth_token="placeholder", **kwargs)
@property
def auth_token(self) -> str:
return self._auth_token_provider()
@auth_token.setter
def auth_token(self, _value): pass
That's 12 lines every customer has to copy. Worth pulling into the SDK.
Repro
Working example: https://github.com/Azure-Samples/claude (see src/hello_claude_token_refresh.py).
Versions
anthropic 0.97.0
- Python 3.11
Most enterprise customers are required by policy to use short-lived, identity-broker-issued bearer tokens (Microsoft Entra ID, Okta, Ping, Vault) instead of long-lived API keys. API keys are hard to rotate, hard to scope per user, hard to audit, and a frequent source of incidents when they leak into logs, CI configs, or repos.
Today the
Anthropicclient supports this only partially.auth_token: str | Noneaccepts a bearer token, but the value is captured once at construction. Tokens from these brokers expire (Entra is ~1h), so any long-running process gets401 Unauthorizedand there's no clean way to refresh without subclassing or wiring a customhttpx.Auth.Accepting a callable would let customers wire their existing identity provider directly:
If it's a string, behave like today. If it's a callable, call it per request when building the
Authorizationheader.Why it matters for Anthropic
openaiPython SDK acceptsapi_key: str | None | Callable[[], str], so this is the pattern customers already standardize on.self.auth_tokenvia a property on every request, so the wiring is mostly in place.Workaround in use today
That's 12 lines every customer has to copy. Worth pulling into the SDK.
Repro
Working example: https://github.com/Azure-Samples/claude (see
src/hello_claude_token_refresh.py).Versions
anthropic0.97.0