stytch 6.4.0 → 9.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # !!!
4
+ # WARNING: This file is autogenerated
5
+ # Only modify code within MANUAL() sections
6
+ # or your changes may be overwritten later!
7
+ # !!!
8
+
9
+ require_relative 'request_helper'
10
+
11
+ module Stytch
12
+ class Project
13
+ include Stytch::RequestHelper
14
+
15
+ def initialize(connection)
16
+ @connection = connection
17
+ end
18
+
19
+ def metrics
20
+ headers = {}
21
+ query_params = {}
22
+ request = request_with_query_params('/v1/projects/metrics', query_params)
23
+ get_request(request, headers)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'errors'
4
+ require_relative 'request_helper'
5
+
6
+ module StytchB2B
7
+ class PolicyCache
8
+ def initialize(rbac_client:)
9
+ @rbac_client = rbac_client
10
+ @policy_last_update = 0
11
+ @cached_policy = nil
12
+ end
13
+
14
+ def reload_policy
15
+ @cached_policy = @rbac_client.policy['policy']
16
+ @policy_last_update = Time.now.to_i
17
+ end
18
+
19
+ def get_policy(invalidate: false)
20
+ reload_policy if invalidate || @cached_policy.nil? || @policy_last_update < Time.now.to_i - 300
21
+ @cached_policy
22
+ end
23
+
24
+ # Performs an authorization check against the project's policy and a set of roles. If the
25
+ # check succeeds, this method will return. If the check fails, a PermissionError
26
+ # will be raised. It's also possible for a TenancyError to be raised if the
27
+ # subject_org_id does not match the authZ request organization_id.
28
+ # authorization_check is an object with keys 'action', 'resource_id', and 'organization_id'
29
+ def perform_authorization_check(
30
+ subject_roles:,
31
+ subject_org_id:,
32
+ authorization_check:
33
+ )
34
+ request_org_id = authorization_check['organization_id']
35
+ raise Stytch::TenancyError.new(subject_org_id, request_org_id) if request_org_id != subject_org_id
36
+
37
+ policy = get_policy
38
+
39
+ for role in policy['roles']
40
+ next unless subject_roles.include?(role['role_id'])
41
+
42
+ for permission in role['permissions']
43
+ actions = permission['actions']
44
+ resource = permission['resource_id']
45
+ has_matching_action = actions.include?('*') || actions.include?(authorization_check['action'])
46
+ has_matching_resource = resource == authorization_check['resource_id']
47
+ if has_matching_action && has_matching_resource
48
+ # All good
49
+ return
50
+ end
51
+ end
52
+ end
53
+
54
+ # If we get here, we didn't find a matching permission
55
+ raise Stytch::PermissionError, authorization_check
56
+ end
57
+ end
58
+ end
@@ -2,29 +2,33 @@
2
2
 
3
3
  module Stytch
4
4
  module RequestHelper
5
- def get_request(path)
5
+ def get_request(path, headers)
6
6
  @connection.get(
7
- path
7
+ path,
8
+ headers
8
9
  ).body
9
10
  end
10
11
 
11
- def post_request(path, payload)
12
+ def post_request(path, payload, headers)
12
13
  @connection.post(
13
14
  path,
14
- payload
15
+ payload,
16
+ headers
15
17
  ).body
16
18
  end
17
19
 
18
- def put_request(path, payload)
20
+ def put_request(path, payload, headers)
19
21
  @connection.put(
20
22
  path,
21
- payload
23
+ payload,
24
+ headers
22
25
  ).body
23
26
  end
24
27
 
25
- def delete_request(path)
28
+ def delete_request(path, headers)
26
29
  @connection.delete(
27
- path
30
+ path,
31
+ headers
28
32
  ).body
29
33
  end
30
34
 
@@ -54,14 +54,17 @@ module Stytch
54
54
  def get(
55
55
  user_id:
56
56
  )
57
+ headers = {}
57
58
  query_params = {
58
59
  user_id: user_id
59
60
  }
60
61
  request = request_with_query_params('/v1/sessions', query_params)
61
- get_request(request)
62
+ get_request(request, headers)
62
63
  end
63
64
 
64
- # Authenticate a session token and retrieve associated session data. If `session_duration_minutes` is included, update the lifetime of the session to be that many minutes from now. All timestamps are formatted according to the RFC 3339 standard and are expressed in UTC, e.g. `2021-12-29T12:33:09Z`. This endpoint requires exactly one `session_jwt` or `session_token` as part of the request. If both are included you will receive a `too_many_session_arguments` error.
65
+ # Authenticate a session token or session JWT and retrieve associated session data. If `session_duration_minutes` is included, update the lifetime of the session to be that many minutes from now. All timestamps are formatted according to the RFC 3339 standard and are expressed in UTC, e.g. `2021-12-29T12:33:09Z`. This endpoint requires exactly one `session_jwt` or `session_token` as part of the request. If both are included, you will receive a `too_many_session_arguments` error.
66
+ #
67
+ # You may provide a JWT that needs to be refreshed and is expired according to its `exp` claim. A new JWT will be returned if both the signature and the underlying Session are still valid. See our [How to use Stytch Session JWTs](https://stytch.com/docs/guides/sessions/using-jwts) guide for more information.
65
68
  #
66
69
  # == Parameters:
67
70
  # session_token::
@@ -108,13 +111,14 @@ module Stytch
108
111
  session_jwt: nil,
109
112
  session_custom_claims: nil
110
113
  )
114
+ headers = {}
111
115
  request = {}
112
116
  request[:session_token] = session_token unless session_token.nil?
113
117
  request[:session_duration_minutes] = session_duration_minutes unless session_duration_minutes.nil?
114
118
  request[:session_jwt] = session_jwt unless session_jwt.nil?
115
119
  request[:session_custom_claims] = session_custom_claims unless session_custom_claims.nil?
116
120
 
117
- post_request('/v1/sessions/authenticate', request)
121
+ post_request('/v1/sessions/authenticate', request, headers)
118
122
  end
119
123
 
120
124
  # Revoke a Session, immediately invalidating all of its session tokens. You can revoke a session in three ways: using its ID, or using one of its session tokens, or one of its JWTs. This endpoint requires exactly one of those to be included in the request. It will return an error if multiple are present.
@@ -143,15 +147,90 @@ module Stytch
143
147
  session_token: nil,
144
148
  session_jwt: nil
145
149
  )
150
+ headers = {}
146
151
  request = {}
147
152
  request[:session_id] = session_id unless session_id.nil?
148
153
  request[:session_token] = session_token unless session_token.nil?
149
154
  request[:session_jwt] = session_jwt unless session_jwt.nil?
150
155
 
151
- post_request('/v1/sessions/revoke', request)
156
+ post_request('/v1/sessions/revoke', request, headers)
152
157
  end
153
158
 
154
- # Get the JSON Web Key Set (JWKS) for a Stytch Project.
159
+ # Migrate a session from an external OIDC compliant endpoint. Stytch will call the external UserInfo endpoint defined in your Stytch Project settings in the [Dashboard](/dashboard), and then perform a lookup using the `session_token`. If the response contains a valid email address, Stytch will attempt to match that email address with an existing User and create a Stytch Session. You will need to create the user before using this endpoint.
160
+ #
161
+ # == Parameters:
162
+ # session_token::
163
+ # The authorization token Stytch will pass in to the external userinfo endpoint.
164
+ # The type of this field is +String+.
165
+ # session_duration_minutes::
166
+ # Set the session lifetime to be this many minutes from now. This will start a new session if one doesn't already exist,
167
+ # returning both an opaque `session_token` and `session_jwt` for this session. Remember that the `session_jwt` will have a fixed lifetime of
168
+ # five minutes regardless of the underlying session duration, and will need to be refreshed over time.
169
+ #
170
+ # This value must be a minimum of 5 and a maximum of 527040 minutes (366 days).
171
+ #
172
+ # If a `session_token` or `session_jwt` is provided then a successful authentication will continue to extend the session this many minutes.
173
+ #
174
+ # If the `session_duration_minutes` parameter is not specified, a Stytch session will not be created.
175
+ # The type of this field is nilable +Integer+.
176
+ # session_custom_claims::
177
+ # Add a custom claims map to the Session being authenticated. Claims are only created if a Session is initialized by providing a value in `session_duration_minutes`. Claims will be included on the Session object and in the JWT. To update a key in an existing Session, supply a new value. To delete a key, supply a null value.
178
+ #
179
+ # Custom claims made with reserved claims ("iss", "sub", "aud", "exp", "nbf", "iat", "jti") will be ignored. Total custom claims size cannot exceed four kilobytes.
180
+ # The type of this field is nilable +object+.
181
+ #
182
+ # == Returns:
183
+ # An object with the following fields:
184
+ # request_id::
185
+ # Globally unique UUID that is returned with every API call. This value is important to log for debugging purposes; we may ask for this value to help identify a specific API call when helping you debug an issue.
186
+ # The type of this field is +String+.
187
+ # user_id::
188
+ # The unique ID of the affected User.
189
+ # The type of this field is +String+.
190
+ # session_token::
191
+ # A secret token for a given Stytch Session.
192
+ # The type of this field is +String+.
193
+ # session_jwt::
194
+ # The JSON Web Token (JWT) for a given Stytch Session.
195
+ # The type of this field is +String+.
196
+ # user::
197
+ # The `user` object affected by this API call. See the [Get user endpoint](https://stytch.com/docs/api/get-user) for complete response field details.
198
+ # The type of this field is +User+ (+object+).
199
+ # status_code::
200
+ # (no documentation yet)
201
+ # The type of this field is +Integer+.
202
+ # session::
203
+ # If you initiate a Session, by including `session_duration_minutes` in your authenticate call, you'll receive a full Session object in the response.
204
+ #
205
+ # See [GET sessions](https://stytch.com/docs/api/session-get) for complete response fields.
206
+ #
207
+ # The type of this field is nilable +Session+ (+object+).
208
+ def migrate(
209
+ session_token:,
210
+ session_duration_minutes: nil,
211
+ session_custom_claims: nil
212
+ )
213
+ headers = {}
214
+ request = {
215
+ session_token: session_token
216
+ }
217
+ request[:session_duration_minutes] = session_duration_minutes unless session_duration_minutes.nil?
218
+ request[:session_custom_claims] = session_custom_claims unless session_custom_claims.nil?
219
+
220
+ post_request('/v1/sessions/migrate', request, headers)
221
+ end
222
+
223
+ # Get the JSON Web Key Set (JWKS) for a project.
224
+ #
225
+ # JWKS are rotated every ~6 months. Upon rotation, new JWTs will be signed using the new key set, and both key sets will be returned by this endpoint for a period of 1 month.
226
+ #
227
+ # JWTs have a set lifetime of 5 minutes, so there will be a 5 minute period where some JWTs will be signed by the old JWKS, and some JWTs will be signed by the new JWKS. The correct JWKS to use for validation is determined by matching the `kid` value of the JWT and JWKS.
228
+ #
229
+ # If you're using one of our [backend SDKs](https://stytch.com/docs/sdks), the JWKS roll will be handled for you.
230
+ #
231
+ # If you're using your own JWT validation library, many have built-in support for JWKS rotation, and you'll just need to supply this API endpoint. If not, your application should decide which JWKS to use for validation by inspecting the `kid` value.
232
+ #
233
+ # See our [How to use Stytch Session JWTs](https://stytch.com/docs/guides/sessions/using-jwts) guide for more information.
155
234
  #
156
235
  # == Parameters:
157
236
  # project_id::
@@ -172,9 +251,10 @@ module Stytch
172
251
  def get_jwks(
173
252
  project_id:
174
253
  )
254
+ headers = {}
175
255
  query_params = {}
176
256
  request = request_with_query_params("/v1/sessions/jwks/#{project_id}", query_params)
177
- get_request(request)
257
+ get_request(request, headers)
178
258
  end
179
259
 
180
260
  # MANUAL(Sessions::authenticate_jwt)(SERVICE_METHOD)
@@ -186,12 +266,18 @@ module Stytch
186
266
  # If max_token_age_seconds is set and the JWT was issued (based on the "iat" claim) less than
187
267
  # max_token_age_seconds seconds ago, then just verify locally and don't call the API
188
268
  # To force remote validation for all tokens, set max_token_age_seconds to 0 or call authenticate()
269
+ # If max_token_age_seconds is not supplied 300 seconds will be used as the default.
270
+ # If clock_tolerance_seconds is not supplied 0 seconds will be used as the default.
189
271
  def authenticate_jwt(
190
272
  session_jwt,
191
273
  max_token_age_seconds: nil,
192
274
  session_duration_minutes: nil,
193
- session_custom_claims: nil
275
+ session_custom_claims: nil,
276
+ clock_tolerance_seconds: nil
194
277
  )
278
+ max_token_age_seconds = 300 if max_token_age_seconds.nil?
279
+ clock_tolerance_seconds = 0 if clock_tolerance_seconds.nil?
280
+
195
281
  if max_token_age_seconds == 0
196
282
  return authenticate(
197
283
  session_jwt: session_jwt,
@@ -200,18 +286,18 @@ module Stytch
200
286
  )
201
287
  end
202
288
 
203
- decoded_jwt = authenticate_jwt_local(session_jwt)
204
- iat_time = Time.at(decoded_jwt['iat']).to_datetime
205
- if iat_time + max_token_age_seconds >= Time.now
206
- session = marshal_jwt_into_session(decoded_jwt)
207
- { 'session' => session }
208
- else
209
- authenticate(
210
- session_jwt: session_jwt,
211
- session_duration_minutes: session_duration_minutes,
212
- session_custom_claims: session_custom_claims
213
- )
214
- end
289
+ session = authenticate_jwt_local(
290
+ session_jwt,
291
+ max_token_age_seconds: max_token_age_seconds,
292
+ clock_tolerance_seconds: clock_tolerance_seconds
293
+ )
294
+ return session unless session.nil?
295
+
296
+ authenticate(
297
+ session_jwt: session_jwt,
298
+ session_duration_minutes: session_duration_minutes,
299
+ session_custom_claims: session_custom_claims
300
+ )
215
301
  rescue StandardError
216
302
  # JWT could not be verified locally. Check with the Stytch API.
217
303
  authenticate(
@@ -225,12 +311,22 @@ module Stytch
225
311
  # Uses the cached value to get the JWK but if it is unavailable, it calls the get_jwks()
226
312
  # function to get the JWK
227
313
  # This method never authenticates a JWT directly with the API
228
- def authenticate_jwt_local(session_jwt)
314
+ # If max_token_age_seconds is not supplied 300 seconds will be used as the default.
315
+ # If clock_tolerance_seconds is not supplied 0 seconds will be used as the default.
316
+ def authenticate_jwt_local(session_jwt, max_token_age_seconds: nil, clock_tolerance_seconds: nil)
317
+ max_token_age_seconds = 300 if max_token_age_seconds.nil?
318
+ clock_tolerance_seconds = 0 if clock_tolerance_seconds.nil?
319
+
229
320
  issuer = 'stytch.com/' + @project_id
230
321
  begin
231
322
  decoded_token = JWT.decode session_jwt, nil, true,
232
- { jwks: @jwks_loader, iss: issuer, verify_iss: true, aud: @project_id, verify_aud: true, algorithms: ['RS256'] }
233
- decoded_token[0]
323
+ { jwks: @jwks_loader, iss: issuer, verify_iss: true, aud: @project_id, verify_aud: true, algorithms: ['RS256'], nbf_leeway: clock_tolerance_seconds }
324
+
325
+ session = decoded_token[0]
326
+ iat_time = Time.at(session['iat']).to_datetime
327
+ return nil unless iat_time + max_token_age_seconds >= Time.now
328
+
329
+ session = marshal_jwt_into_session(session)
234
330
  rescue JWT::InvalidIssuerError
235
331
  raise JWTInvalidIssuerError
236
332
  rescue JWT::InvalidAudError
@@ -240,6 +336,8 @@ module Stytch
240
336
  rescue JWT::IncorrectAlgorithm
241
337
  raise JWTIncorrectAlgorithmError
242
338
  end
339
+
340
+ session
243
341
  end
244
342
 
245
343
  def marshal_jwt_into_session(jwt)
@@ -251,15 +349,17 @@ module Stytch
251
349
  reserved_claims = ['aud', 'exp', 'iat', 'iss', 'jti', 'nbf', 'sub', stytch_claim]
252
350
  custom_claims = jwt.reject { |key, _| reserved_claims.include?(key) }
253
351
  {
254
- 'session_id' => jwt[stytch_claim]['id'],
255
- 'user_id' => jwt['sub'],
256
- 'started_at' => jwt[stytch_claim]['started_at'],
257
- 'last_accessed_at' => jwt[stytch_claim]['last_accessed_at'],
258
- # For JWTs that include it, prefer the inner expires_at claim.
259
- 'expires_at' => expires_at,
260
- 'attributes' => jwt[stytch_claim]['attributes'],
261
- 'authentication_factors' => jwt[stytch_claim]['authentication_factors'],
262
- 'custom_claims' => custom_claims
352
+ 'session' => {
353
+ 'session_id' => jwt[stytch_claim]['id'],
354
+ 'user_id' => jwt['sub'],
355
+ 'started_at' => jwt[stytch_claim]['started_at'],
356
+ 'last_accessed_at' => jwt[stytch_claim]['last_accessed_at'],
357
+ # For JWTs that include it, prefer the inner expires_at claim.
358
+ 'expires_at' => expires_at,
359
+ 'attributes' => jwt[stytch_claim]['attributes'],
360
+ 'authentication_factors' => jwt[stytch_claim]['authentication_factors'],
361
+ 'custom_claims' => custom_claims
362
+ }
263
363
  }
264
364
  end
265
365
  # ENDMANUAL(Sessions::authenticate_jwt)
data/lib/stytch/totps.rb CHANGED
@@ -23,7 +23,7 @@ module Stytch
23
23
  # The `user_id` of an active user the TOTP registration should be tied to.
24
24
  # The type of this field is +String+.
25
25
  # expiration_minutes::
26
- # The expiration for the TOTP instance. If the newly created TOTP is not authenticated within this time frame the TOTP will be unusable. Defaults to 60 (1 hour) with a minimum of 5 and a maximum of 1440.
26
+ # The expiration for the TOTP instance. If the newly created TOTP is not authenticated within this time frame the TOTP will be unusable. Defaults to 1440 (1 day) with a minimum of 5 and a maximum of 1440.
27
27
  # The type of this field is nilable +Integer+.
28
28
  #
29
29
  # == Returns:
@@ -56,12 +56,13 @@ module Stytch
56
56
  user_id:,
57
57
  expiration_minutes: nil
58
58
  )
59
+ headers = {}
59
60
  request = {
60
61
  user_id: user_id
61
62
  }
62
63
  request[:expiration_minutes] = expiration_minutes unless expiration_minutes.nil?
63
64
 
64
- post_request('/v1/totps', request)
65
+ post_request('/v1/totps', request, headers)
65
66
  end
66
67
 
67
68
  # Authenticate a TOTP code entered by a user.
@@ -133,6 +134,7 @@ module Stytch
133
134
  session_jwt: nil,
134
135
  session_custom_claims: nil
135
136
  )
137
+ headers = {}
136
138
  request = {
137
139
  user_id: user_id,
138
140
  totp_code: totp_code
@@ -142,7 +144,7 @@ module Stytch
142
144
  request[:session_jwt] = session_jwt unless session_jwt.nil?
143
145
  request[:session_custom_claims] = session_custom_claims unless session_custom_claims.nil?
144
146
 
145
- post_request('/v1/totps/authenticate', request)
147
+ post_request('/v1/totps/authenticate', request, headers)
146
148
  end
147
149
 
148
150
  # Retrieve the recovery codes for a TOTP instance tied to a User.
@@ -169,11 +171,12 @@ module Stytch
169
171
  def recovery_codes(
170
172
  user_id:
171
173
  )
174
+ headers = {}
172
175
  request = {
173
176
  user_id: user_id
174
177
  }
175
178
 
176
- post_request('/v1/totps/recovery_codes', request)
179
+ post_request('/v1/totps/recovery_codes', request, headers)
177
180
  end
178
181
 
179
182
  # Authenticate a recovery code for a TOTP instance.
@@ -245,6 +248,7 @@ module Stytch
245
248
  session_jwt: nil,
246
249
  session_custom_claims: nil
247
250
  )
251
+ headers = {}
248
252
  request = {
249
253
  user_id: user_id,
250
254
  recovery_code: recovery_code
@@ -254,7 +258,7 @@ module Stytch
254
258
  request[:session_jwt] = session_jwt unless session_jwt.nil?
255
259
  request[:session_custom_claims] = session_custom_claims unless session_custom_claims.nil?
256
260
 
257
- post_request('/v1/totps/recover', request)
261
+ post_request('/v1/totps/recover', request, headers)
258
262
  end
259
263
  end
260
264
  end
data/lib/stytch/users.rb CHANGED
@@ -77,6 +77,7 @@ module Stytch
77
77
  trusted_metadata: nil,
78
78
  untrusted_metadata: nil
79
79
  )
80
+ headers = {}
80
81
  request = {}
81
82
  request[:email] = email unless email.nil?
82
83
  request[:name] = name unless name.nil?
@@ -86,7 +87,7 @@ module Stytch
86
87
  request[:trusted_metadata] = trusted_metadata unless trusted_metadata.nil?
87
88
  request[:untrusted_metadata] = untrusted_metadata unless untrusted_metadata.nil?
88
89
 
89
- post_request('/v1/users', request)
90
+ post_request('/v1/users', request, headers)
90
91
  end
91
92
 
92
93
  # Get information about a specific User.
@@ -114,7 +115,7 @@ module Stytch
114
115
  # An array of phone number objects linked to the User.
115
116
  # The type of this field is list of +PhoneNumber+ (+object+).
116
117
  # webauthn_registrations::
117
- # An array that contains a list of all WebAuthn registrations for a given User in the Stytch API.
118
+ # An array that contains a list of all Passkey or WebAuthn registrations for a given User in the Stytch API.
118
119
  # The type of this field is list of +WebAuthnRegistration+ (+object+).
119
120
  # providers::
120
121
  # An array of OAuth `provider` objects linked to the User.
@@ -149,9 +150,10 @@ module Stytch
149
150
  def get(
150
151
  user_id:
151
152
  )
153
+ headers = {}
152
154
  query_params = {}
153
155
  request = request_with_query_params("/v1/users/#{user_id}", query_params)
154
- get_request(request)
156
+ get_request(request, headers)
155
157
  end
156
158
 
157
159
  # Search for Users within your Stytch Project. Submit an empty `query` in the request to return all Users.
@@ -186,17 +188,18 @@ module Stytch
186
188
  limit: nil,
187
189
  query: nil
188
190
  )
191
+ headers = {}
189
192
  request = {}
190
193
  request[:cursor] = cursor unless cursor.nil?
191
194
  request[:limit] = limit unless limit.nil?
192
195
  request[:query] = query unless query.nil?
193
196
 
194
- post_request('/v1/users/search', request)
197
+ post_request('/v1/users/search', request, headers)
195
198
  end
196
199
 
197
200
  # Update a User's attributes.
198
201
  #
199
- # **Note:** In order to add a new email address or phone number to an existing User object, pass the new email address or phone number into the respective `/send` endpoint for the authentication method of your choice. If you specify the existing User's `user_id` while calling the `/send` endpoint, the new email address or phone number will be added to the existing User object upon successful authentication. We require this process to guard against an account takeover vulnerability.
202
+ # **Note:** In order to add a new email address or phone number to an existing User object, pass the new email address or phone number into the respective `/send` endpoint for the authentication method of your choice. If you specify the existing User's `user_id` while calling the `/send` endpoint, the new, unverified email address or phone number will be added to the existing User object. If the user successfully authenticates within 5 minutes of the `/send` request, the new email address or phone number will be marked as verified and remain permanently on the existing Stytch User. Otherwise, it will be removed from the User object, and any subsequent login requests using that phone number will create a new User. We require this process to guard against an account takeover vulnerability.
200
203
  #
201
204
  # == Parameters:
202
205
  # user_id::
@@ -245,13 +248,14 @@ module Stytch
245
248
  trusted_metadata: nil,
246
249
  untrusted_metadata: nil
247
250
  )
251
+ headers = {}
248
252
  request = {}
249
253
  request[:name] = name unless name.nil?
250
254
  request[:attributes] = attributes unless attributes.nil?
251
255
  request[:trusted_metadata] = trusted_metadata unless trusted_metadata.nil?
252
256
  request[:untrusted_metadata] = untrusted_metadata unless untrusted_metadata.nil?
253
257
 
254
- put_request("/v1/users/#{user_id}", request)
258
+ put_request("/v1/users/#{user_id}", request, headers)
255
259
  end
256
260
 
257
261
  # Exchange a user's email address or phone number for another.
@@ -292,11 +296,12 @@ module Stytch
292
296
  email_address: nil,
293
297
  phone_number: nil
294
298
  )
299
+ headers = {}
295
300
  request = {}
296
301
  request[:email_address] = email_address unless email_address.nil?
297
302
  request[:phone_number] = phone_number unless phone_number.nil?
298
303
 
299
- put_request("/v1/users/#{user_id}/exchange_primary_factor", request)
304
+ put_request("/v1/users/#{user_id}/exchange_primary_factor", request, headers)
300
305
  end
301
306
 
302
307
  # Delete a User from Stytch.
@@ -320,7 +325,8 @@ module Stytch
320
325
  def delete(
321
326
  user_id:
322
327
  )
323
- delete_request("/v1/users/#{user_id}")
328
+ headers = {}
329
+ delete_request("/v1/users/#{user_id}", headers)
324
330
  end
325
331
 
326
332
  # Delete an email from a User.
@@ -347,7 +353,8 @@ module Stytch
347
353
  def delete_email(
348
354
  email_id:
349
355
  )
350
- delete_request("/v1/users/emails/#{email_id}")
356
+ headers = {}
357
+ delete_request("/v1/users/emails/#{email_id}", headers)
351
358
  end
352
359
 
353
360
  # Delete a phone number from a User.
@@ -374,7 +381,8 @@ module Stytch
374
381
  def delete_phone_number(
375
382
  phone_id:
376
383
  )
377
- delete_request("/v1/users/phone_numbers/#{phone_id}")
384
+ headers = {}
385
+ delete_request("/v1/users/phone_numbers/#{phone_id}", headers)
378
386
  end
379
387
 
380
388
  # Delete a WebAuthn registration from a User.
@@ -401,7 +409,8 @@ module Stytch
401
409
  def delete_webauthn_registration(
402
410
  webauthn_registration_id:
403
411
  )
404
- delete_request("/v1/users/webauthn_registrations/#{webauthn_registration_id}")
412
+ headers = {}
413
+ delete_request("/v1/users/webauthn_registrations/#{webauthn_registration_id}", headers)
405
414
  end
406
415
 
407
416
  # Delete a biometric registration from a User.
@@ -428,7 +437,8 @@ module Stytch
428
437
  def delete_biometric_registration(
429
438
  biometric_registration_id:
430
439
  )
431
- delete_request("/v1/users/biometric_registrations/#{biometric_registration_id}")
440
+ headers = {}
441
+ delete_request("/v1/users/biometric_registrations/#{biometric_registration_id}", headers)
432
442
  end
433
443
 
434
444
  # Delete a TOTP from a User.
@@ -455,7 +465,8 @@ module Stytch
455
465
  def delete_totp(
456
466
  totp_id:
457
467
  )
458
- delete_request("/v1/users/totps/#{totp_id}")
468
+ headers = {}
469
+ delete_request("/v1/users/totps/#{totp_id}", headers)
459
470
  end
460
471
 
461
472
  # Delete a crypto wallet from a User.
@@ -482,7 +493,8 @@ module Stytch
482
493
  def delete_crypto_wallet(
483
494
  crypto_wallet_id:
484
495
  )
485
- delete_request("/v1/users/crypto_wallets/#{crypto_wallet_id}")
496
+ headers = {}
497
+ delete_request("/v1/users/crypto_wallets/#{crypto_wallet_id}", headers)
486
498
  end
487
499
 
488
500
  # Delete a password from a User.
@@ -509,7 +521,8 @@ module Stytch
509
521
  def delete_password(
510
522
  password_id:
511
523
  )
512
- delete_request("/v1/users/passwords/#{password_id}")
524
+ headers = {}
525
+ delete_request("/v1/users/passwords/#{password_id}", headers)
513
526
  end
514
527
 
515
528
  # Delete an OAuth registration from a User.
@@ -536,7 +549,8 @@ module Stytch
536
549
  def delete_oauth_registration(
537
550
  oauth_user_registration_id:
538
551
  )
539
- delete_request("/v1/users/oauth/#{oauth_user_registration_id}")
552
+ headers = {}
553
+ delete_request("/v1/users/oauth/#{oauth_user_registration_id}", headers)
540
554
  end
541
555
  end
542
556
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Stytch
4
- VERSION = '6.4.0'
4
+ VERSION = '9.8.0'
5
5
  end