Class: Anthropic::Credentials::WorkloadIdentity

Inherits:
Object
  • Object
show all
Defined in:
lib/anthropic/credentials/workload_identity.rb

Overview

Exchanges an external OIDC JWT for an Anthropic access token via the RFC 7523 jwt-bearer grant.

This is an access token provider: calling it performs a fresh token exchange. Wrap in a TokenCache (done automatically when passed as credentials: to Anthropic::Client) to avoid exchanging on every request.

Constant Summary collapse

MAX_ASSERTION_BYTES =

Maximum size in bytes for the identity token JWT. JWTs from real IdPs are <4 KiB; a 16 KiB ceiling catches misconfiguration.

16 * 1024

Instance Method Summary collapse

Constructor Details

#initialize(identity_token_provider:, federation_rule_id:, organization_id:, service_account_id: nil, workspace_id: nil, scope: nil) ⇒ WorkloadIdentity

Returns a new instance of WorkloadIdentity.

Parameters:

  • identity_token_provider (#call)

    callable that returns the external OIDC JWT string (e.g., IdentityTokenFile or a Proc/lambda)

  • federation_rule_id (String)

    the federation rule ID configured in the Anthropic Console

  • organization_id (String)

    the organization’s raw UUID string

  • service_account_id (String, nil) (defaults to: nil)

    optional service account ID to impersonate

  • workspace_id (String, nil) (defaults to: nil)

    Optional wrkspc_* tagged ID, or the literal “default” to scope the token to the organization’s default workspace. When omitted the server picks the rule’s sole enabled workspace, else the org default if the rule covers it. Required when the rule enables more than one non-default workspace, or to target a specific workspace other than the one the server would pick. The minted token is workspace-scoped: per-request workspace selection (the anthropic-workspace-id header) is not supported for federation tokens — switching workspaces requires a new token exchange with a different workspace_id.

  • scope (String, nil) (defaults to: nil)

    optional OAuth scope (informational only for federation; the server derives the effective scope from the federation rule)



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/anthropic/credentials/workload_identity.rb', line 68

def initialize(
  identity_token_provider:,
  federation_rule_id:,
  organization_id:,
  service_account_id: nil,
  workspace_id: nil,
  scope: nil # rubocop:disable Lint/UnusedMethodArgument
)
  @identity_token_provider = identity_token_provider
  @federation_rule_id = federation_rule_id
  @organization_id = organization_id
  @service_account_id = 
  @workspace_id = workspace_id
  @bound_base_url = nil
end

Instance Method Details

#bind_base_url(base_url) ⇒ void

This method returns an undefined value.

Sets the API base_url the token exchange POSTs to.

Called by Anthropic::Client when this object is passed as credentials:, so callers don’t pass the same URL twice. For standalone use (no client) or tests, call this directly.

Parameters:

  • base_url (String)

    the API base URL (must be HTTPS except for localhost)

Raises:



93
94
95
96
97
# File 'lib/anthropic/credentials/workload_identity.rb', line 93

def bind_base_url(base_url)
  bound = base_url.to_s.chomp("/")
  Anthropic::Config.require_https!(bound, field: "base_url")
  @bound_base_url = bound
end

#call(force_refresh: false) ⇒ AccessToken

Performs the token exchange and returns an access token.

Re-invokes the identity token provider on every call — the underlying file or environment variable may have rotated.

Parameters:

  • force_refresh (Boolean) (defaults to: false)

    ignored; this provider has no cache to bypass

Returns:

  • (AccessToken)

    the exchanged access token with expiry

Raises:



107
108
109
110
111
112
113
114
115
116
# File 'lib/anthropic/credentials/workload_identity.rb', line 107

def call(force_refresh: false) # rubocop:disable Lint/UnusedMethodArgument
  jwt = @identity_token_provider.call

  if jwt.bytesize > MAX_ASSERTION_BYTES
    raise WorkloadIdentityError,
          "Identity token assertion is #{jwt.bytesize} bytes, exceeding #{MAX_ASSERTION_BYTES}-byte limit"
  end

  perform_exchange(jwt)
end