Skip to content

Commit 8af0b4d

Browse files
authored
Merge pull request #1520 from stainless-sdks/dev/jtian/remove-unnecessary-params
[feat] Remove unnecessary params client id during init
2 parents 93272ba + c6dcfe0 commit 8af0b4d

5 files changed

Lines changed: 45 additions & 20 deletions

File tree

README.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ Note that you can also pass a raw `IO` descriptor, but this disables retries, as
111111

112112
For secure, automated environments like cloud-managed Kubernetes, Azure, and GCP, you can use workload identity authentication with short-lived tokens from cloud identity providers instead of long-lived API keys.
113113

114+
`client_id` remains available as an optional parameter for token exchange setups that require an explicit OAuth client ID.
114115

115116
### Kubernetes Service Account
116117

@@ -121,7 +122,6 @@ require "openai"
121122
provider = OpenAI::Auth::SubjectTokenProviders::K8sServiceAccountTokenProvider.new
122123

123124
workload_identity = OpenAI::Auth::WorkloadIdentity.new(
124-
client_id: ENV["OAUTH_CLIENT_ID"], # This is the default and can be omitted
125125
identity_provider_id: ENV["IDENTITY_PROVIDER_ID"], # This is the default and can be omitted
126126
service_account_id: ENV["SERVICE_ACCOUNT_ID"], # This is the default and can be omitted
127127
provider: provider
@@ -143,7 +143,6 @@ response = client.chat.completions.create(
143143
provider = OpenAI::Auth::SubjectTokenProviders::AzureManagedIdentityTokenProvider.new
144144

145145
workload_identity = OpenAI::Auth::WorkloadIdentity.new(
146-
client_id: ENV["OAUTH_CLIENT_ID"], # This is the default and can be omitted
147146
identity_provider_id: ENV["IDENTITY_PROVIDER_ID"], # This is the default and can be omitted
148147
service_account_id: ENV["SERVICE_ACCOUNT_ID"], # This is the default and can be omitted
149148
provider: provider
@@ -160,7 +159,6 @@ client = OpenAI::Client.new(
160159
provider = OpenAI::Auth::SubjectTokenProviders::GCPIDTokenProvider.new
161160

162161
workload_identity = OpenAI::Auth::WorkloadIdentity.new(
163-
client_id: ENV["OAUTH_CLIENT_ID"], # This is the default and can be omitted
164162
identity_provider_id: ENV["IDENTITY_PROVIDER_ID"], # This is the default and can be omitted
165163
service_account_id: ENV["SERVICE_ACCOUNT_ID"], # This is the default and can be omitted
166164
provider: provider
@@ -191,7 +189,6 @@ end
191189
provider = CustomProvider.new
192190

193191
workload_identity = OpenAI::Auth::WorkloadIdentity.new(
194-
client_id: ENV["OAUTH_CLIENT_ID"], # This is the default and can be omitted
195192
identity_provider_id: ENV["IDENTITY_PROVIDER_ID"], # This is the default and can be omitted
196193
service_account_id: ENV["SERVICE_ACCOUNT_ID"], # This is the default and can be omitted
197194
provider: provider

lib/openai/auth/workload_identity.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ class WorkloadIdentity
66
attr_reader :client_id, :identity_provider_id, :service_account_id, :provider, :refresh_buffer_seconds
77

88
def initialize(
9-
client_id:,
109
identity_provider_id:,
1110
service_account_id:,
1211
provider:,
12+
client_id: nil,
1313
refresh_buffer_seconds: 1200
1414
)
15-
@client_id = client_id.to_s
15+
@client_id = client_id&.to_s
1616
@identity_provider_id = identity_provider_id.to_s
1717
@service_account_id = service_account_id.to_s
1818
@provider = provider

lib/openai/auth/workload_identity_auth.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,15 @@ def fetch_token_from_exchange
9292

9393
request = Net::HTTP::Post.new(@token_exchange_url)
9494
request["Content-Type"] = "application/json"
95-
request.body = JSON.generate(
95+
body = {
9696
grant_type: TOKEN_EXCHANGE_GRANT_TYPE,
97-
client_id: @config.client_id,
9897
subject_token: subject_token,
9998
subject_token_type: subject_token_type,
10099
identity_provider_id: @config.identity_provider_id,
101100
service_account_id: @config.service_account_id
102-
)
101+
}
102+
body[:client_id] = @config.client_id unless @config.client_id.nil?
103+
request.body = JSON.generate(body)
103104

104105
response = Net::HTTP.start(
105106
@token_exchange_url.hostname,

rbi/openai/auth.rbi

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ module OpenAI
1818
end
1919

2020
class WorkloadIdentity
21-
sig { returns(String) }
21+
sig { returns(T.nilable(String)) }
2222
attr_reader :client_id
2323

2424
sig { returns(String) }
@@ -35,18 +35,18 @@ module OpenAI
3535

3636
sig do
3737
params(
38-
client_id: T.any(String, Symbol),
3938
identity_provider_id: T.any(String, Symbol),
4039
service_account_id: T.any(String, Symbol),
4140
provider: SubjectTokenProvider,
41+
client_id: T.nilable(T.any(String, Symbol)),
4242
refresh_buffer_seconds: Integer
4343
).void
4444
end
4545
def initialize(
46-
client_id:,
4746
identity_provider_id:,
4847
service_account_id:,
4948
provider:,
49+
client_id: nil,
5050
refresh_buffer_seconds: 1200
5151
)
5252
end

test/openai/auth/workload_identity_test.rb

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,39 @@ def test_workload_identity_auth_token_exchange
119119
token_path: @token_path
120120
)
121121

122+
stub_request(:post, "https://auth.openai.com/oauth/token")
123+
.with do |request|
124+
JSON.parse(request.body) == {
125+
"grant_type" => "urn:ietf:params:oauth:grant-type:token-exchange",
126+
"subject_token" => "k8s-jwt-token",
127+
"subject_token_type" => "urn:ietf:params:oauth:token-type:jwt",
128+
"identity_provider_id" => "idp-123",
129+
"service_account_id" => "sa-456"
130+
}
131+
end
132+
.to_return(
133+
status: 200,
134+
body: JSON.generate({"access_token" => "oauth-access-token", "expires_in" => 3600})
135+
)
136+
137+
config = OpenAI::Auth::WorkloadIdentity.new(
138+
identity_provider_id: "idp-123",
139+
service_account_id: "sa-456",
140+
provider: provider
141+
)
142+
143+
auth = OpenAI::Auth::WorkloadIdentityAuth.new(config, "org-123")
144+
token = auth.get_token
145+
146+
assert_equal("oauth-access-token", token)
147+
end
148+
149+
def test_workload_identity_auth_token_exchange_with_optional_client_id
150+
File.write(@token_path, "k8s-jwt-token")
151+
provider = OpenAI::Auth::SubjectTokenProviders::K8sServiceAccountTokenProvider.new(
152+
token_path: @token_path
153+
)
154+
122155
stub_request(:post, "https://auth.openai.com/oauth/token")
123156
.with(
124157
body: hash_including(
@@ -136,10 +169,10 @@ def test_workload_identity_auth_token_exchange
136169
)
137170

138171
config = OpenAI::Auth::WorkloadIdentity.new(
139-
client_id: "test-client",
140172
identity_provider_id: "idp-123",
141173
service_account_id: "sa-456",
142-
provider: provider
174+
provider: provider,
175+
client_id: "test-client"
143176
)
144177

145178
auth = OpenAI::Auth::WorkloadIdentityAuth.new(config, "org-123")
@@ -166,7 +199,6 @@ def test_workload_identity_auth_oauth_error
166199
)
167200

168201
config = OpenAI::Auth::WorkloadIdentity.new(
169-
client_id: "bad-client",
170202
identity_provider_id: "idp-123",
171203
service_account_id: "sa-456",
172204
provider: provider
@@ -190,7 +222,6 @@ def test_workload_identity_client_initialization
190222
)
191223

192224
config = OpenAI::Auth::WorkloadIdentity.new(
193-
client_id: "test-client",
194225
identity_provider_id: "idp-123",
195226
service_account_id: "sa-456",
196227
provider: provider
@@ -210,7 +241,6 @@ def test_workload_identity_client_initialization
210241
def test_workload_identity_mutually_exclusive_with_api_key
211242
provider = OpenAI::Auth::SubjectTokenProviders::K8sServiceAccountTokenProvider.new
212243
config = OpenAI::Auth::WorkloadIdentity.new(
213-
client_id: "test-client",
214244
identity_provider_id: "idp-123",
215245
service_account_id: "sa-456",
216246
provider: provider
@@ -233,7 +263,6 @@ def test_workload_identity_preserves_admin_auth_requests
233263
token_path: @token_path
234264
)
235265
config = OpenAI::Auth::WorkloadIdentity.new(
236-
client_id: "test-client",
237266
identity_provider_id: "idp-123",
238267
service_account_id: "sa-456",
239268
provider: provider
@@ -316,7 +345,6 @@ def test_401_retry_with_token_invalidation
316345
)
317346

318347
config = OpenAI::Auth::WorkloadIdentity.new(
319-
client_id: "test-client",
320348
identity_provider_id: "idp-123",
321349
service_account_id: "sa-456",
322350
provider: provider
@@ -379,7 +407,6 @@ def test_workload_identity_token_caching
379407
)
380408

381409
config = OpenAI::Auth::WorkloadIdentity.new(
382-
client_id: "test-client",
383410
identity_provider_id: "idp-123",
384411
service_account_id: "sa-456",
385412
provider: provider

0 commit comments

Comments
 (0)