zitadel-client 4.1.0.beta.11 → 4.1.0.beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79e492c7af7e1aab9fcd95807b1a796f6ada6044d00fcdc35c3b43222c6f70de
4
- data.tar.gz: 626804c4543a8af3656aa0b9b18df3cd2dbdc5e4730d08a0927c7e61fd246763
3
+ metadata.gz: 80b99719c332eacba3f9dfda861860033c67f1cc0864a9cdf01606bc9b042bc5
4
+ data.tar.gz: 8df3848854d1d8b66d0cd36ff4803a43d3b48b03d97c16f7fd0ede5978d75099
5
5
  SHA512:
6
- metadata.gz: 7e6338a7155c80e9fff2f0cac83dc62e876de0cefdefbb131cddc8a41531d577a20d3236ce6c2d73fa9f69953d7fb5d191dd2d3274a74b0fc9caa925def571b1
7
- data.tar.gz: 94527eb37dd943ec99651529f6ac798b91419faf9a06046eac42c7c54d50248b355df40d466c8b1fbc0715942906fe5f6bd14af7003633184d92bf838aa46154
6
+ metadata.gz: 7eb3b8f2e95066c5fd89e28419bb4d98e40b6829651ff1c276a4a230affdb6c8422f7be4fb7c66eea19fb137eb9e7ff95b324c37339b91b45b788c570129e2d8
7
+ data.tar.gz: 93208352051b9a5b31a58c78d2cc684a6a1dc3be4cf64b635447b07f4902cb08c37e602715df0fb2c5e87045ae2c49824941f87ff8adb0b85ceaf8a1c7775737
data/README.md CHANGED
@@ -194,22 +194,99 @@ environment and security requirements. For more details, please refer to the
194
194
  ### Debugging
195
195
 
196
196
  The SDK supports debug logging, which can be enabled for troubleshooting
197
- and debugging purposes. You can enable debug logging by setting the `debug`
198
- flag to `true` when initializing the `Zitadel` client, like this:
197
+ and debugging purposes. You can enable debug logging by setting `debugging`
198
+ to `true` via the configuration block when initializing the `Zitadel` client:
199
199
 
200
200
  ```ruby
201
- zitadel = zitadel.Zitadel("your-zitadel-base-url", 'your-valid-token', lambda config: config.debug = True)
201
+ zitadel = Zitadel::Client::Zitadel.with_access_token(
202
+ 'your-zitadel-base-url',
203
+ 'your-valid-token'
204
+ ) do |config|
205
+ config.debugging = true
206
+ end
202
207
  ```
203
208
 
204
209
  When enabled, the SDK will log additional information, such as HTTP request
205
210
  and response details, which can be useful for identifying issues in the
206
211
  integration or troubleshooting unexpected behavior.
207
212
 
213
+ ## Advanced Configuration
214
+
215
+ The SDK provides a `TransportOptions` object that allows you to customise
216
+ the underlying HTTP transport used for both OpenID discovery and API calls.
217
+
218
+ ### Disabling TLS Verification
219
+
220
+ In development or testing environments with self-signed certificates, you can
221
+ disable TLS verification entirely:
222
+
223
+ ```ruby
224
+ options = Zitadel::Client::TransportOptions.new(insecure: true)
225
+
226
+ zitadel = Zitadel::Client::Zitadel.with_client_credentials(
227
+ 'https://your-instance.zitadel.cloud',
228
+ 'client-id',
229
+ 'client-secret',
230
+ transport_options: options
231
+ )
232
+ ```
233
+
234
+ ### Using a Custom CA Certificate
235
+
236
+ If your Zitadel instance uses a certificate signed by a private CA, you can
237
+ provide the path to the CA certificate in PEM format:
238
+
239
+ ```ruby
240
+ options = Zitadel::Client::TransportOptions.new(ca_cert_path: '/path/to/ca.pem')
241
+
242
+ zitadel = Zitadel::Client::Zitadel.with_client_credentials(
243
+ 'https://your-instance.zitadel.cloud',
244
+ 'client-id',
245
+ 'client-secret',
246
+ transport_options: options
247
+ )
248
+ ```
249
+
250
+ ### Custom Default Headers
251
+
252
+ You can attach default headers to every outgoing request. This is useful for
253
+ custom routing or tracing headers:
254
+
255
+ ```ruby
256
+ options = Zitadel::Client::TransportOptions.new(
257
+ default_headers: { 'X-Custom-Header' => 'my-value' }
258
+ )
259
+
260
+ zitadel = Zitadel::Client::Zitadel.with_client_credentials(
261
+ 'https://your-instance.zitadel.cloud',
262
+ 'client-id',
263
+ 'client-secret',
264
+ transport_options: options
265
+ )
266
+ ```
267
+
268
+ ### Proxy Configuration
269
+
270
+ If your environment requires routing traffic through an HTTP proxy, you can
271
+ specify the proxy URL. To authenticate with the proxy, embed the credentials
272
+ directly in the URL:
273
+
274
+ ```ruby
275
+ options = Zitadel::Client::TransportOptions.new(proxy_url: 'http://user:pass@proxy:8080')
276
+
277
+ zitadel = Zitadel::Client::Zitadel.with_client_credentials(
278
+ 'https://your-instance.zitadel.cloud',
279
+ 'client-id',
280
+ 'client-secret',
281
+ transport_options: options
282
+ )
283
+ ```
284
+
208
285
  ## Design and Dependencies
209
286
 
210
287
  This SDK is designed to be lean and efficient, focusing on providing a
211
288
  streamlined way to interact with the Zitadel API. It relies on the commonly used
212
- urllib3 HTTP transport for making requests, which ensures that
289
+ Typhoeus HTTP library for making requests, which ensures that
213
290
  the SDK integrates well with other libraries and provides flexibility
214
291
  in terms of request handling and error management.
215
292
 
@@ -48,7 +48,7 @@ module Zitadel
48
48
  @default_headers = {
49
49
  'Content-Type' => 'application/json',
50
50
  'User-Agent' => config.user_agent
51
- }
51
+ }.merge(config.default_headers || {})
52
52
  end
53
53
 
54
54
  # noinspection RubyClassVariableUsageInspection,RbsMissingTypeSignature
@@ -114,6 +114,9 @@ module Zitadel
114
114
  # set custom cert, if provided
115
115
  req_opts[:cainfo] = @config.ssl_ca_cert if @config.ssl_ca_cert
116
116
 
117
+ # set proxy, if provided
118
+ req_opts[:proxy] = @config.proxy_url if @config.proxy_url
119
+
117
120
  if %i[post patch put delete].include?(http_method)
118
121
  req_body = build_request_body(header_params, form_params, opts[:body])
119
122
  req_opts.update body: req_body
@@ -56,9 +56,12 @@ module Zitadel
56
56
  # Initializes the OAuthAuthenticatorBuilder with a given host.
57
57
  #
58
58
  # @param host [String] the base URL for the OAuth provider.
59
+ # @param transport_options [TransportOptions, nil] Optional transport options for TLS, proxy, and headers.
59
60
  #
60
- def initialize(host)
61
- @open_id = OpenId.new(host)
61
+ def initialize(host, transport_options: nil)
62
+ transport_options ||= TransportOptions.defaults
63
+ @transport_options = transport_options
64
+ @open_id = OpenId.new(host, transport_options: transport_options)
62
65
  @auth_scopes = Set.new(%w[openid urn:zitadel:iam:org:project:id:zitadel:aud])
63
66
  end
64
67
 
@@ -11,12 +11,18 @@ module Zitadel
11
11
  # @param client_id [String] The OAuth client identifier.
12
12
  # @param client_secret [String] The OAuth client secret.
13
13
  # @param auth_scopes [Set<String>] The scope(s) for the token request.
14
- def initialize(open_id, client_id, client_secret, auth_scopes)
14
+ # @param transport_options [TransportOptions, nil] Optional transport options for TLS, proxy, and headers.
15
+ def initialize(open_id, client_id, client_secret, auth_scopes, transport_options: nil)
16
+ transport_options ||= TransportOptions.defaults
17
+
18
+ conn_opts = transport_options.to_connection_opts
19
+
15
20
  # noinspection RubyArgCount
16
21
  super(open_id, auth_scopes, OAuth2::Client.new(client_id, client_secret, {
17
22
  site: open_id.host_endpoint,
18
- token_url: open_id.token_endpoint
19
- }))
23
+ token_url: open_id.token_endpoint,
24
+ connection_opts: conn_opts
25
+ }), transport_options: transport_options)
20
26
  end
21
27
 
22
28
  # Returns a new builder for constructing a ClientCredentialsAuthenticator.
@@ -24,9 +30,11 @@ module Zitadel
24
30
  # @param host [String] The OAuth provider's base URL.
25
31
  # @param client_id [String] The OAuth client identifier.
26
32
  # @param client_secret [String] The OAuth client secret.
33
+ # @param transport_options [TransportOptions, nil] Optional transport options for TLS, proxy, and headers.
27
34
  # @return [ClientCredentialsAuthenticatorBuilder] A builder instance.
28
- def self.builder(host, client_id, client_secret)
29
- ClientCredentialsAuthenticatorBuilder.new(host, client_id, client_secret)
35
+ def self.builder(host, client_id, client_secret, transport_options: nil)
36
+ ClientCredentialsAuthenticatorBuilder.new(host, client_id, client_secret,
37
+ transport_options: transport_options)
30
38
  end
31
39
 
32
40
  protected
@@ -45,9 +53,10 @@ module Zitadel
45
53
  # @param host [String] The OAuth provider's base URL.
46
54
  # @param client_id [String] The OAuth client identifier.
47
55
  # @param client_secret [String] The OAuth client secret.
48
- def initialize(host, client_id, client_secret)
56
+ # @param transport_options [TransportOptions, nil] Optional transport options for TLS, proxy, and headers.
57
+ def initialize(host, client_id, client_secret, transport_options: nil)
49
58
  # noinspection RubyArgCount
50
- super(host)
59
+ super(host, transport_options: transport_options)
51
60
  @client_id = client_id
52
61
  @client_secret = client_secret
53
62
  end
@@ -56,7 +65,8 @@ module Zitadel
56
65
  #
57
66
  # @return [ClientCredentialsAuthenticator] A configured instance.
58
67
  def build
59
- ClientCredentialsAuthenticator.new(open_id, @client_id, @client_secret, auth_scopes)
68
+ ClientCredentialsAuthenticator.new(open_id, @client_id, @client_secret, auth_scopes,
69
+ transport_options: @transport_options)
60
70
  end
61
71
  end
62
72
  end
@@ -25,11 +25,14 @@ module Zitadel
25
25
  # Constructs an OAuthAuthenticator.
26
26
  #
27
27
  # @param open_id [OpenId] An object that must implement `get_host_endpoint` and `get_token_endpoint`.
28
- # @param auth_session [OAuth2Session] The OAuth2Session instance used for token requests.
28
+ # @param auth_scopes [Set<String>] The scope(s) for the token request.
29
+ # @param auth_session [OAuth2::Client] The OAuth2 client instance used for token requests.
30
+ # @param transport_options [TransportOptions, nil] Optional transport options for TLS, proxy, and headers.
29
31
  #
30
- def initialize(open_id, auth_scopes, auth_session)
32
+ def initialize(open_id, auth_scopes, auth_session, transport_options: nil)
31
33
  super(open_id.host_endpoint)
32
34
  @open_id = open_id
35
+ @transport_options = transport_options || TransportOptions.defaults
33
36
  @token = nil
34
37
  @auth_session = auth_session
35
38
  @auth_scopes = auth_scopes.to_a.join(' ')
@@ -3,6 +3,7 @@
3
3
  require 'json'
4
4
  require 'uri'
5
5
  require 'net/http'
6
+ require 'openssl'
6
7
 
7
8
  module Zitadel
8
9
  module Client
@@ -20,16 +21,38 @@ module Zitadel
20
21
  # Initializes a new OpenId instance.
21
22
  #
22
23
  # @param hostname [String] the hostname for the OpenID provider.
24
+ # @param transport_options [TransportOptions, nil] Optional transport options for TLS, proxy, and headers.
23
25
  # @raise [RuntimeError] if the OpenID configuration cannot be fetched or the token_endpoint is missing.
24
26
  #
25
27
  # noinspection HttpUrlsUsage
26
- def initialize(hostname)
28
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
29
+ def initialize(hostname, transport_options: nil)
30
+ transport_options ||= TransportOptions.defaults
27
31
  hostname = "https://#{hostname}" unless hostname.start_with?('http://', 'https://')
28
32
  @host_endpoint = hostname
29
33
  well_known_url = self.class.build_well_known_url(hostname)
30
34
 
31
35
  uri = URI.parse(well_known_url)
32
- response = Net::HTTP.get_response(uri)
36
+ http = if transport_options.proxy_url
37
+ proxy_uri = URI.parse(transport_options.proxy_url)
38
+ Net::HTTP.new(uri.host.to_s, uri.port, proxy_uri.host, proxy_uri.port,
39
+ proxy_uri.user, proxy_uri.password)
40
+ else
41
+ Net::HTTP.new(uri.host.to_s, uri.port)
42
+ end
43
+ http.use_ssl = (uri.scheme == 'https')
44
+ if transport_options.insecure
45
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
46
+ elsif transport_options.ca_cert_path
47
+ store = OpenSSL::X509::Store.new
48
+ store.set_default_paths
49
+ store.add_file(transport_options.ca_cert_path)
50
+ http.cert_store = store
51
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
52
+ end
53
+ request = Net::HTTP::Get.new(uri)
54
+ transport_options.default_headers.each { |k, v| request[k] = v }
55
+ response = http.request(request)
33
56
  raise "Failed to fetch OpenID configuration: HTTP #{response.code}" unless response.code.to_i == 200
34
57
 
35
58
  config = JSON.parse(response.body)
@@ -38,6 +61,7 @@ module Zitadel
38
61
 
39
62
  @token_endpoint = token_endpoint
40
63
  end
64
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
41
65
 
42
66
  ##
43
67
  # Builds the well-known OpenID configuration URL for the given hostname.
@@ -25,14 +25,20 @@ module Zitadel
25
25
  # @param jwt_lifetime [Integer] Lifetime of the JWT in seconds (default 3600 seconds).
26
26
  # @param jwt_algorithm [String] The JWT signing algorithm (default "RS256").
27
27
  # @param key_id [String, nil] Optional key identifier for the JWT header (default: nil).
28
- # rubocop:disable Metrics/ParameterLists,Metrics/MethodLength
28
+ # @param transport_options [TransportOptions, nil] Optional transport options for TLS, proxy, and headers.
29
+ # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
29
30
  def initialize(open_id, auth_scopes, jwt_issuer, jwt_subject, jwt_audience, private_key,
30
- jwt_lifetime: 3600, jwt_algorithm: 'RS256', key_id: nil)
31
+ jwt_lifetime: 3600, jwt_algorithm: 'RS256', key_id: nil, transport_options: nil)
32
+ transport_options ||= TransportOptions.defaults
33
+
34
+ conn_opts = transport_options.to_connection_opts
35
+
31
36
  # noinspection RubyArgCount,RubyMismatchedArgumentType
32
37
  super(open_id, auth_scopes, OAuth2::Client.new('zitadel', 'zitadel', {
33
38
  site: open_id.host_endpoint,
34
- token_url: open_id.token_endpoint
35
- }))
39
+ token_url: open_id.token_endpoint,
40
+ connection_opts: conn_opts
41
+ }), transport_options: transport_options)
36
42
  @jwt_issuer = jwt_issuer
37
43
  @jwt_subject = jwt_subject
38
44
  @jwt_audience = jwt_audience
@@ -47,7 +53,7 @@ module Zitadel
47
53
  end
48
54
  end
49
55
 
50
- # rubocop:enable Metrics/ParameterLists,Metrics/MethodLength
56
+ # rubocop:enable Metrics/ParameterLists, Metrics/MethodLength
51
57
 
52
58
  # Creates a WebTokenAuthenticator instance from a JSON configuration file.
53
59
  #
@@ -62,9 +68,11 @@ module Zitadel
62
68
  #
63
69
  # @param host [String] Base URL for the API endpoints.
64
70
  # @param json_path [String] File path to the JSON configuration file.
71
+ # @param transport_options [TransportOptions, nil] Optional transport options for TLS, proxy, and headers.
65
72
  # @return [WebTokenAuthenticator] A new instance of WebTokenAuthenticator.
66
73
  # @raise [RuntimeError] If the file cannot be read, the JSON is invalid, or required keys are missing.
67
- def self.from_json(host, json_path)
74
+ # rubocop:disable Metrics/MethodLength
75
+ def self.from_json(host, json_path, transport_options: nil)
68
76
  config = JSON.parse(File.read(json_path))
69
77
  rescue Errno::ENOENT => e
70
78
  raise "Unable to read JSON file at #{json_path}: #{e.message}"
@@ -76,17 +84,21 @@ module Zitadel
76
84
  user_id, private_key, key_id = config.values_at('userId', 'key', 'keyId')
77
85
  raise "Missing required keys 'userId', 'keyId' or 'key'" unless user_id && key_id && private_key
78
86
 
79
- WebTokenAuthenticator.builder(host, user_id, private_key).key_identifier(key_id).build
87
+ WebTokenAuthenticator.builder(host, user_id, private_key, transport_options: transport_options)
88
+ .key_identifier(key_id).build
80
89
  end
90
+ # rubocop:enable Metrics/MethodLength
81
91
 
82
92
  # Returns a builder for constructing a WebTokenAuthenticator.
83
93
  #
84
94
  # @param host [String] The base URL for the OAuth provider.
85
95
  # @param user_id [String] The user identifier (used as both the issuer and subject).
86
96
  # @param private_key [String] The private key used to sign the JWT.
97
+ # @param transport_options [TransportOptions, nil] Optional transport options for TLS, proxy, and headers.
87
98
  # @return [WebTokenAuthenticatorBuilder] A builder instance.
88
- def self.builder(host, user_id, private_key)
89
- WebTokenAuthenticatorBuilder.new(host, user_id, user_id, host, private_key)
99
+ def self.builder(host, user_id, private_key, transport_options: nil)
100
+ WebTokenAuthenticatorBuilder.new(host, user_id, user_id, host, private_key,
101
+ transport_options: transport_options)
90
102
  end
91
103
 
92
104
  protected
@@ -130,15 +142,18 @@ module Zitadel
130
142
  # @param jwt_subject [String] The subject claim for the JWT.
131
143
  # @param jwt_audience [String] The audience claim for the JWT.
132
144
  # @param private_key [String] The PEM-formatted private key used for signing the JWT.
133
- def initialize(host, jwt_issuer, jwt_subject, jwt_audience, private_key)
145
+ # @param transport_options [TransportOptions, nil] Optional transport options for TLS, proxy, and headers.
146
+ # rubocop:disable Metrics/ParameterLists
147
+ def initialize(host, jwt_issuer, jwt_subject, jwt_audience, private_key, transport_options: nil)
134
148
  # noinspection RubyArgCount
135
- super(host)
149
+ super(host, transport_options: transport_options)
136
150
  @jwt_issuer = jwt_issuer
137
151
  @jwt_subject = jwt_subject
138
152
  @jwt_audience = jwt_audience
139
153
  @private_key = private_key
140
154
  @jwt_lifetime = 3600
141
155
  end
156
+ # rubocop:enable Metrics/ParameterLists
142
157
 
143
158
  # Sets the JWT token lifetime in seconds.
144
159
  #
@@ -159,7 +174,8 @@ module Zitadel
159
174
  # @return [WebTokenAuthenticator] A configured instance.
160
175
  def build
161
176
  WebTokenAuthenticator.new(open_id, auth_scopes, @jwt_issuer, @jwt_subject, @jwt_audience,
162
- @private_key, jwt_lifetime: @jwt_lifetime, key_id: @key_id)
177
+ @private_key, jwt_lifetime: @jwt_lifetime, key_id: @key_id,
178
+ transport_options: @transport_options)
163
179
  end
164
180
  end
165
181
  end
@@ -149,6 +149,24 @@ module Zitadel
149
149
  # @return [String, nil]
150
150
  attr_accessor :user_agent
151
151
 
152
+ ##
153
+ # Additional headers to include in every HTTP request.
154
+ #
155
+ # These headers are merged with the default headers set by the API client.
156
+ # Defaults to an empty hash.
157
+ #
158
+ # @return [Hash{String => String}]
159
+ attr_accessor :default_headers
160
+
161
+ ##
162
+ # Proxy URL to use for HTTP requests.
163
+ #
164
+ # When set, all HTTP requests will be routed through the specified proxy.
165
+ # The URL should include the scheme, host, and port (e.g., "http://proxy:8080").
166
+ #
167
+ # @return [String, nil]
168
+ attr_accessor :proxy_url
169
+
152
170
  # rubocop:disable Metrics/MethodLength
153
171
  def initialize(authenticator = Auth::NoAuthAuthenticator.new)
154
172
  @authenticator = authenticator
@@ -157,6 +175,8 @@ module Zitadel
157
175
  @verify_ssl_host = true
158
176
  @cert_file = nil
159
177
  @key_file = nil
178
+ @default_headers = {}
179
+ @proxy_url = nil
160
180
  @timeout = 0
161
181
  @params_encoding = nil
162
182
  @debugging = false
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openssl'
4
+
5
+ module Zitadel
6
+ module Client
7
+ # Immutable transport options for configuring HTTP connections.
8
+ class TransportOptions
9
+ # @return [Hash{String => String}] Default HTTP headers sent to the origin server with every request.
10
+ attr_reader :default_headers
11
+
12
+ # @return [String, nil] Path to a custom CA certificate file for TLS verification.
13
+ attr_reader :ca_cert_path
14
+
15
+ # @return [Boolean] Whether to disable TLS certificate verification.
16
+ attr_reader :insecure
17
+
18
+ # @return [String, nil] Proxy URL for HTTP connections.
19
+ attr_reader :proxy_url
20
+
21
+ # Creates a new TransportOptions instance.
22
+ #
23
+ # @param default_headers [Hash{String => String}] Default HTTP headers sent to the origin server with every request.
24
+ # @param ca_cert_path [String, nil] Path to a custom CA certificate file for TLS verification.
25
+ # @param insecure [Boolean] Whether to disable TLS certificate verification.
26
+ # @param proxy_url [String, nil] Proxy URL for HTTP connections.
27
+ # @return [TransportOptions] an immutable transport options instance.
28
+ def initialize(default_headers: {}, ca_cert_path: nil, insecure: false, proxy_url: nil)
29
+ @default_headers = default_headers.dup.freeze
30
+ @ca_cert_path = ca_cert_path&.dup&.freeze
31
+ @insecure = insecure
32
+ @proxy_url = proxy_url&.dup&.freeze
33
+ freeze
34
+ end
35
+
36
+ # Returns a TransportOptions instance with all default values.
37
+ #
38
+ # @return [TransportOptions] a default transport options instance.
39
+ def self.defaults
40
+ new
41
+ end
42
+
43
+ # Builds Faraday connection options from these transport options.
44
+ #
45
+ # @return [Hash] connection options for OAuth2::Client
46
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
47
+ def to_connection_opts
48
+ opts = {}
49
+ if insecure
50
+ opts[:ssl] = { verify: false }
51
+ elsif ca_cert_path
52
+ store = OpenSSL::X509::Store.new
53
+ store.set_default_paths
54
+ store.add_file(ca_cert_path)
55
+ opts[:ssl] = { cert_store: store, verify: true }
56
+ end
57
+ opts[:proxy] = proxy_url if proxy_url
58
+ opts[:headers] = default_headers.dup if default_headers.any?
59
+ opts
60
+ end
61
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
62
+ end
63
+ end
64
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Zitadel
4
4
  module Client
5
- VERSION = '4.1.0.beta.11'
5
+ VERSION = '4.1.0.beta.12'
6
6
  end
7
7
  end
@@ -7,7 +7,7 @@ module Zitadel
7
7
  # Initializes and configures the SDK with the provided authentication strategy.
8
8
  # Sets up service APIs for interacting with various Zitadel features.
9
9
  # noinspection RubyTooManyInstanceVariablesInspection
10
- class Zitadel
10
+ class Zitadel # rubocop:disable Metrics/ClassLength
11
11
  attr_reader :features,
12
12
  :idps,
13
13
  :instances,
@@ -90,10 +90,15 @@ module Zitadel
90
90
  #
91
91
  # @param host [String] API URL (e.g. "https://api.zitadel.example.com").
92
92
  # @param access_token [String] Personal Access Token for Bearer authentication.
93
- # @return [Zitadel] SDK client configured with PAT authentication.
93
+ # @param transport_options [TransportOptions, nil] Optional transport options for TLS, proxy, and headers.
94
+ # @return [Zitadel] Configured Zitadel client instance.
94
95
  # @see https://zitadel.com/docs/guides/integrate/service-users/personal-access-token
95
- def with_access_token(host, access_token)
96
- new(Auth::PersonalAccessTokenAuthenticator.new(host, access_token))
96
+ def with_access_token(host, access_token, transport_options: nil, &block)
97
+ resolved = transport_options || TransportOptions.defaults
98
+ new(Auth::PersonalAccessTokenAuthenticator.new(host, access_token)) do |config|
99
+ apply_transport_options(config, resolved)
100
+ block&.call(config)
101
+ end
97
102
  end
98
103
 
99
104
  # Initialize the SDK using OAuth2 Client Credentials flow.
@@ -101,27 +106,50 @@ module Zitadel
101
106
  # @param host [String] API URL.
102
107
  # @param client_id [String] OAuth2 client identifier.
103
108
  # @param client_secret [String] OAuth2 client secret.
104
- # @return [Zitadel] SDK client with automatic token acquisition & refresh.
109
+ # @param transport_options [TransportOptions, nil] Optional transport options for TLS, proxy, and headers.
110
+ # @return [Zitadel] Configured Zitadel client instance with token auto-refresh.
105
111
  # @see https://zitadel.com/docs/guides/integrate/service-users/client-credentials
106
- def with_client_credentials(host, client_id, client_secret)
112
+ def with_client_credentials(host, client_id, client_secret, transport_options: nil, &block)
113
+ resolved = transport_options || TransportOptions.defaults
107
114
  new(
108
115
  Auth::ClientCredentialsAuthenticator
109
- .builder(host, client_id, client_secret)
116
+ .builder(host, client_id, client_secret, transport_options: resolved)
110
117
  .build
111
- )
118
+ ) do |config|
119
+ apply_transport_options(config, resolved)
120
+ block&.call(config)
121
+ end
112
122
  end
113
123
 
114
124
  # Initialize the SDK via Private Key JWT assertion.
115
125
  #
116
126
  # @param host [String] API URL.
117
127
  # @param key_file [String] Path to service account JSON/PEM key file.
118
- # @return [Zitadel] SDK client using JWT assertion for secure, secret-less auth.
128
+ # @param transport_options [TransportOptions, nil] Optional transport options for TLS, proxy, and headers.
129
+ # @return [Zitadel] Configured Zitadel client instance using JWT assertion.
119
130
  # @see https://zitadel.com/docs/guides/integrate/service-users/private-key-jwt
120
- def with_private_key(host, key_file)
121
- new(Auth::WebTokenAuthenticator.from_json(host, key_file))
131
+ def with_private_key(host, key_file, transport_options: nil, &block)
132
+ resolved = transport_options || TransportOptions.defaults
133
+ new(Auth::WebTokenAuthenticator.from_json(host, key_file,
134
+ transport_options: resolved)) do |config|
135
+ apply_transport_options(config, resolved)
136
+ block&.call(config)
137
+ end
122
138
  end
123
139
 
124
140
  # @!endgroup
141
+
142
+ private
143
+
144
+ def apply_transport_options(config, resolved)
145
+ config.default_headers = resolved.default_headers.dup
146
+ config.ssl_ca_cert = resolved.ca_cert_path if resolved.ca_cert_path
147
+ if resolved.insecure
148
+ config.verify_ssl = false
149
+ config.verify_ssl_host = false
150
+ end
151
+ config.proxy_url = resolved.proxy_url if resolved.proxy_url
152
+ end
125
153
  end
126
154
  end
127
155
  end
@@ -85,7 +85,7 @@ module OAuth2
85
85
  end
86
86
 
87
87
  class Client
88
- def initialize: (String | nil, String | nil, Hash[Symbol, String]) -> void
88
+ def initialize: (String | nil, String | nil, Hash[Symbol, untyped]) -> void
89
89
 
90
90
  def fetch_token: (url: String, **untyped) -> AccessToken
91
91
 
data/sig/lib.rbs CHANGED
@@ -132,6 +132,8 @@ module Zitadel
132
132
  attr_accessor cert_file: String?
133
133
  attr_accessor key_file: String?
134
134
  attr_accessor params_encoding: Symbol?
135
+ attr_accessor default_headers: Hash[String, String]
136
+ attr_accessor proxy_url: String?
135
137
 
136
138
  def self.default: () -> Configuration
137
139
 
@@ -202,6 +204,16 @@ module Zitadel
202
204
  def initialize: (Integer, Hash[String, Array[String]], String | Typhoeus::Response) -> void
203
205
  end
204
206
 
207
+ class TransportOptions
208
+ attr_reader default_headers: Hash[String, String]
209
+ attr_reader ca_cert_path: String?
210
+ attr_reader insecure: bool
211
+ attr_reader proxy_url: String?
212
+ def initialize: (?default_headers: Hash[String, String], ?ca_cert_path: String?, ?insecure: bool, ?proxy_url: String?) -> void
213
+ def self.defaults: -> TransportOptions
214
+ def to_connection_opts: -> Hash[Symbol, untyped]
215
+ end
216
+
205
217
  module Auth
206
218
 
207
219
  class Authenticator
@@ -217,17 +229,17 @@ module Zitadel
217
229
 
218
230
  class ClientCredentialsAuthenticator < OAuthAuthenticator
219
231
 
220
- def initialize: (OpenId, String, String, Set[String]) -> void
232
+ def initialize: (OpenId, String, String, Set[String], ?transport_options: TransportOptions?) -> void
221
233
 
222
234
  def get_grant: (OAuth2::Client, String) -> OAuth2::AccessToken
223
235
 
224
- def self.builder: (String, String, String) -> ClientCredentialsAuthenticatorBuilder
236
+ def self.builder: (String, String, String, ?transport_options: TransportOptions?) -> ClientCredentialsAuthenticatorBuilder
225
237
 
226
238
  class ClientCredentialsAuthenticatorBuilder < OAuthAuthenticatorBuilder
227
239
  @client_id: String
228
240
  @client_secret: String
229
241
 
230
- def initialize: (String, String, String) -> void
242
+ def initialize: (String, String, String, ?transport_options: TransportOptions?) -> void
231
243
 
232
244
  def build: -> ClientCredentialsAuthenticator
233
245
  end
@@ -248,7 +260,7 @@ module Zitadel
248
260
  attr_reader open_id: OpenId
249
261
  attr_reader auth_scopes: Set[String]
250
262
 
251
- def initialize: (String) -> void
263
+ def initialize: (String, ?transport_options: TransportOptions?) -> void
252
264
 
253
265
  def scopes: (*String) -> self
254
266
  end
@@ -259,8 +271,9 @@ module Zitadel
259
271
  @open_id: OpenId
260
272
  @token: OAuth2::AccessToken
261
273
  @auth_scopes: String
274
+ @transport_options: TransportOptions
262
275
 
263
- def initialize: (OpenId, Set[String], OAuth2::Client) -> void
276
+ def initialize: (OpenId, Set[String], OAuth2::Client, ?transport_options: TransportOptions?) -> void
264
277
 
265
278
  def auth_token: () -> String
266
279
 
@@ -278,7 +291,7 @@ module Zitadel
278
291
  attr_accessor host_endpoint: String
279
292
  attr_accessor token_endpoint: String
280
293
 
281
- def initialize: (String) -> void
294
+ def initialize: (String, ?transport_options: TransportOptions?) -> void
282
295
 
283
296
  def self.build_well_known_url: (String) -> String
284
297
  end
@@ -300,13 +313,13 @@ module Zitadel
300
313
  @key_id: String?
301
314
  @private_key: OpenSSL::PKey::RSA
302
315
 
303
- def self.builder: (String, String, String) -> WebTokenAuthenticatorBuilder
316
+ def self.builder: (String, String, String, ?transport_options: TransportOptions?) -> WebTokenAuthenticatorBuilder
304
317
 
305
- def self.from_json: (String, String) -> WebTokenAuthenticator
318
+ def self.from_json: (String, String, ?transport_options: TransportOptions?) -> WebTokenAuthenticator
306
319
 
307
320
  def get_grant: (OAuth2::Client, String) -> OAuth2::AccessToken
308
321
 
309
- def initialize: (OpenId, Set[String], String, String, String, (String | OpenSSL::PKey::PKey), ?jwt_lifetime: Integer, ?jwt_algorithm: String, ?key_id: String?) -> void
322
+ def initialize: (OpenId, Set[String], String, String, String, (String | OpenSSL::PKey::PKey), ?jwt_lifetime: Integer, ?jwt_algorithm: String, ?key_id: String?, ?transport_options: TransportOptions?) -> void
310
323
 
311
324
  class WebTokenAuthenticatorBuilder < OAuthAuthenticatorBuilder
312
325
  @jwt_audience: String
@@ -316,7 +329,7 @@ module Zitadel
316
329
  @key_id: String
317
330
  @private_key: String
318
331
 
319
- def initialize: (String, String, String, String, String) -> void
332
+ def initialize: (String, String, String, String, String, ?transport_options: TransportOptions?) -> void
320
333
 
321
334
  def build: -> WebTokenAuthenticator
322
335
 
@@ -329,11 +342,17 @@ module Zitadel
329
342
 
330
343
  class Zitadel
331
344
 
332
- def self.with_access_token: (String, String) -> Zitadel
345
+ def self.with_access_token: (String, String, ?transport_options: TransportOptions?) ?{ (Configuration) -> void } -> Zitadel
346
+
347
+ def self.with_client_credentials: (String, String, String, ?transport_options: TransportOptions?) ?{ (Configuration) -> void } -> Zitadel
348
+
349
+ def self.with_private_key: (String, String, ?transport_options: TransportOptions?) ?{ (Configuration) -> void } -> Zitadel
350
+
351
+ private
333
352
 
334
- def self.with_client_credentials: (String, String, String) -> Zitadel
353
+ def self.apply_transport_options: (Configuration, TransportOptions) -> void
335
354
 
336
- def self.with_private_key: (String, String) -> Zitadel
355
+ public
337
356
 
338
357
  attr_reader configuration: Configuration
339
358
  attr_reader features: Api::FeatureServiceApi
metadata CHANGED
@@ -1,15 +1,70 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zitadel-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0.beta.11
4
+ version: 4.1.0.beta.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zitadel
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2026-03-03 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: cgi
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0.1'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0.1'
26
+ - !ruby/object:Gem::Dependency
27
+ name: date
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '3.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '3.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: logger
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '1.4'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '1.4'
54
+ - !ruby/object:Gem::Dependency
55
+ name: net-http
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0.1'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0.1'
13
68
  - !ruby/object:Gem::Dependency
14
69
  name: oauth2
15
70
  requirement: !ruby/object:Gem::Requirement
@@ -24,6 +79,34 @@ dependencies:
24
79
  - - "~>"
25
80
  - !ruby/object:Gem::Version
26
81
  version: '2.0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: tempfile
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0.1'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0.1'
96
+ - !ruby/object:Gem::Dependency
97
+ name: time
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0.1'
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0.1'
27
110
  - !ruby/object:Gem::Dependency
28
111
  name: typhoeus
29
112
  requirement: !ruby/object:Gem::Requirement
@@ -44,6 +127,20 @@ dependencies:
44
127
  - - ">="
45
128
  - !ruby/object:Gem::Version
46
129
  version: 1.0.1
130
+ - !ruby/object:Gem::Dependency
131
+ name: uri
132
+ requirement: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0.10'
137
+ type: :runtime
138
+ prerelease: false
139
+ version_requirements: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '0.10'
47
144
  - !ruby/object:Gem::Dependency
48
145
  name: warning
49
146
  requirement: !ruby/object:Gem::Requirement
@@ -1474,6 +1571,7 @@ files:
1474
1571
  - lib/zitadel/client/models/web_key_service_r_s_a_hasher.rb
1475
1572
  - lib/zitadel/client/models/web_key_service_state.rb
1476
1573
  - lib/zitadel/client/models/web_key_service_web_key.rb
1574
+ - lib/zitadel/client/transport_options.rb
1477
1575
  - lib/zitadel/client/utils/url_util.rb
1478
1576
  - lib/zitadel/client/version.rb
1479
1577
  - lib/zitadel/client/zitadel.rb
@@ -1489,7 +1587,6 @@ licenses:
1489
1587
  - Apache-2.0
1490
1588
  metadata:
1491
1589
  rubygems_mfa_required: 'true'
1492
- post_install_message:
1493
1590
  rdoc_options: []
1494
1591
  require_paths:
1495
1592
  - lib
@@ -1500,12 +1597,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
1500
1597
  version: '3.0'
1501
1598
  required_rubygems_version: !ruby/object:Gem::Requirement
1502
1599
  requirements:
1503
- - - ">"
1600
+ - - ">="
1504
1601
  - !ruby/object:Gem::Version
1505
- version: 1.3.1
1602
+ version: '0'
1506
1603
  requirements: []
1507
- rubygems_version: 3.2.33
1508
- signing_key:
1604
+ rubygems_version: 4.0.3
1509
1605
  specification_version: 4
1510
1606
  summary: Official Zitadel SDK for Ruby
1511
1607
  test_files: []