stytch 10.28.0 → 10.30.0
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 +4 -4
- data/lib/stytch/b2b_client.rb +2 -2
- data/lib/stytch/b2b_idp.rb +272 -32
- data/lib/stytch/b2b_organizations.rb +9 -7
- data/lib/stytch/b2b_passwords.rb +10 -7
- data/lib/stytch/b2b_sessions.rb +6 -6
- data/lib/stytch/b2b_sso.rb +62 -0
- data/lib/stytch/client.rb +2 -2
- data/lib/stytch/connected_apps.rb +16 -16
- data/lib/stytch/idp.rb +258 -32
- data/lib/stytch/passwords.rb +3 -2
- data/lib/stytch/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7acf63a684df206a833f253f48357c53529f4bc26570766b1d58336b22416006
|
4
|
+
data.tar.gz: 48c64a6a03cb92b287fe5ac5e07f5a1697cdd37423d2d2421a86ce59208c7c1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c7ae74e4f7d5fd3e50ad70789dbb5b55d81868e0992041aa8c5fe3be27a58dcc667ce2800a1667106ea1a595ff035cb409b84e7fe996af840a3e049428c9be7
|
7
|
+
data.tar.gz: 5b86b4ef7a588d67ca53ea6b93724cbf9c230b7e92548ba12bbcf8352557c177360ed13b1628effa11f1f7f8791445b29a557d0cf26536ddabdfe34f053b63cb
|
data/lib/stytch/b2b_client.rb
CHANGED
@@ -30,7 +30,7 @@ module StytchB2B
|
|
30
30
|
class Client
|
31
31
|
ENVIRONMENTS = %i[live test].freeze
|
32
32
|
|
33
|
-
attr_reader :connected_app, :discovery, :fraud, :impersonation, :m2m, :magic_links, :oauth, :otps, :organizations, :passwords, :project, :rbac, :recovery_codes, :scim, :sso, :sessions, :totps
|
33
|
+
attr_reader :connected_app, :discovery, :fraud, :idp, :impersonation, :m2m, :magic_links, :oauth, :otps, :organizations, :passwords, :project, :rbac, :recovery_codes, :scim, :sso, :sessions, :totps
|
34
34
|
|
35
35
|
def initialize(project_id:, secret:, env: nil, fraud_env: nil, &block)
|
36
36
|
@api_host = api_host(env, project_id)
|
@@ -43,11 +43,11 @@ module StytchB2B
|
|
43
43
|
|
44
44
|
rbac = StytchB2B::RBAC.new(@connection)
|
45
45
|
@policy_cache = Stytch::PolicyCache.new(rbac_client: rbac)
|
46
|
-
@idp = StytchB2B::IDP.new(@connection, @project_id, @policy_cache)
|
47
46
|
|
48
47
|
@connected_app = Stytch::ConnectedApp.new(@connection)
|
49
48
|
@discovery = StytchB2B::Discovery.new(@connection)
|
50
49
|
@fraud = Stytch::Fraud.new(@fraud_connection)
|
50
|
+
@idp = StytchB2B::IDP.new(@connection, @project_id, @policy_cache)
|
51
51
|
@impersonation = StytchB2B::Impersonation.new(@connection)
|
52
52
|
@m2m = Stytch::M2M.new(@connection, @project_id, @is_b2b_client)
|
53
53
|
@magic_links = StytchB2B::MagicLinks.new(@connection)
|
data/lib/stytch/b2b_idp.rb
CHANGED
@@ -1,37 +1,46 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
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
|
+
|
3
9
|
require 'jwt'
|
4
10
|
require 'json/jwt'
|
5
11
|
require_relative 'errors'
|
6
12
|
require_relative 'request_helper'
|
7
|
-
require_relative 'rbac_local'
|
8
13
|
|
9
14
|
module StytchB2B
|
10
15
|
class IDP
|
11
16
|
include Stytch::RequestHelper
|
17
|
+
attr_reader :oauth
|
12
18
|
|
13
19
|
def initialize(connection, project_id, policy_cache)
|
14
20
|
@connection = connection
|
15
|
-
|
21
|
+
|
22
|
+
@oauth = StytchB2B::IDP::OAuth.new(@connection)
|
16
23
|
@policy_cache = policy_cache
|
17
|
-
@
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
'token_type',
|
31
|
-
'https://stytch.com/organization'
|
32
|
-
]
|
24
|
+
@project_id = project_id
|
25
|
+
@cache_last_update = 0
|
26
|
+
@jwks_loader = lambda do |options|
|
27
|
+
@cached_keys = nil if options[:invalidate] && @cache_last_update < Time.now.to_i - 300
|
28
|
+
@cached_keys ||= begin
|
29
|
+
@cache_last_update = Time.now.to_i
|
30
|
+
keys = []
|
31
|
+
get_jwks(project_id: @project_id)['keys'].each do |r|
|
32
|
+
keys << r
|
33
|
+
end
|
34
|
+
{ keys: keys }
|
35
|
+
end
|
36
|
+
end
|
33
37
|
end
|
34
38
|
|
39
|
+
# MANUAL(IDP::introspect_token_network)(SERVICE_METHOD)
|
40
|
+
# ADDIMPORT: require 'jwt'
|
41
|
+
# ADDIMPORT: require 'json/jwt'
|
42
|
+
# ADDIMPORT: require_relative 'errors'
|
43
|
+
|
35
44
|
# Introspects a token JWT from an authorization code response.
|
36
45
|
# Access tokens are JWTs signed with the project's JWKs. Refresh tokens are opaque tokens.
|
37
46
|
# Access tokens contain a standard set of claims as well as any custom claims generated from templates.
|
@@ -105,7 +114,7 @@ module StytchB2B
|
|
105
114
|
|
106
115
|
return nil unless jwt_response['active']
|
107
116
|
|
108
|
-
custom_claims = jwt_response.reject { |k, _|
|
117
|
+
custom_claims = jwt_response.reject { |k, _| non_custom_claim_keys.include?(k) }
|
109
118
|
organization_claim = jwt_response['https://stytch.com/organization']
|
110
119
|
organization_id = organization_claim['organization_id']
|
111
120
|
scope = jwt_response['scope']
|
@@ -183,17 +192,6 @@ module StytchB2B
|
|
183
192
|
scope_claim = 'scope'
|
184
193
|
organization_claim = 'https://stytch.com/organization'
|
185
194
|
|
186
|
-
# Create a JWKS loader similar to other classes in the codebase
|
187
|
-
@cache_last_update = 0
|
188
|
-
jwks_loader = lambda do |options|
|
189
|
-
@cached_keys = nil if options[:invalidate] && @cache_last_update < Time.now.to_i - 300
|
190
|
-
if @cached_keys.nil?
|
191
|
-
@cached_keys = get_jwks(project_id: @project_id)
|
192
|
-
@cache_last_update = Time.now.to_i
|
193
|
-
end
|
194
|
-
@cached_keys
|
195
|
-
end
|
196
|
-
|
197
195
|
begin
|
198
196
|
decoded_jwt = JWT.decode(
|
199
197
|
access_token,
|
@@ -201,14 +199,14 @@ module StytchB2B
|
|
201
199
|
true,
|
202
200
|
{
|
203
201
|
algorithms: ['RS256'],
|
204
|
-
jwks: jwks_loader,
|
202
|
+
jwks: @jwks_loader,
|
205
203
|
iss: ["stytch.com/#{@project_id}", @connection.url_prefix],
|
206
204
|
aud: @project_id
|
207
205
|
}
|
208
206
|
)[0]
|
209
207
|
|
210
208
|
generic_claims = decoded_jwt
|
211
|
-
custom_claims = generic_claims.reject { |k, _|
|
209
|
+
custom_claims = generic_claims.reject { |k, _| non_custom_claim_keys.include?(k) }
|
212
210
|
organization_claim_data = generic_claims[organization_claim]
|
213
211
|
organization_id = organization_claim_data['organization_id']
|
214
212
|
scope = generic_claims[scope_claim]
|
@@ -246,6 +244,27 @@ module StytchB2B
|
|
246
244
|
end
|
247
245
|
end
|
248
246
|
|
247
|
+
private
|
248
|
+
|
249
|
+
def non_custom_claim_keys
|
250
|
+
[
|
251
|
+
'aud',
|
252
|
+
'exp',
|
253
|
+
'iat',
|
254
|
+
'iss',
|
255
|
+
'jti',
|
256
|
+
'nbf',
|
257
|
+
'sub',
|
258
|
+
'active',
|
259
|
+
'client_id',
|
260
|
+
'request_id',
|
261
|
+
'scope',
|
262
|
+
'status_code',
|
263
|
+
'token_type',
|
264
|
+
'https://stytch.com/organization'
|
265
|
+
]
|
266
|
+
end
|
267
|
+
|
249
268
|
# Gets the JWKS for the project.
|
250
269
|
#
|
251
270
|
# == Parameters:
|
@@ -262,5 +281,226 @@ module StytchB2B
|
|
262
281
|
request = request_with_query_params("/v1/b2b/sessions/jwks/#{project_id}", query_params)
|
263
282
|
get_request(request, headers)
|
264
283
|
end
|
284
|
+
|
285
|
+
# ENDMANUAL(IDP::introspect_token_network)
|
286
|
+
|
287
|
+
class OAuth
|
288
|
+
include Stytch::RequestHelper
|
289
|
+
|
290
|
+
def initialize(connection)
|
291
|
+
@connection = connection
|
292
|
+
end
|
293
|
+
|
294
|
+
# Initiates a request for authorization of a Connected App to access a Member's account.
|
295
|
+
#
|
296
|
+
# Call this endpoint using the query parameters from an OAuth Authorization request.
|
297
|
+
# This endpoint validates various fields (`scope`, `client_id`, `redirect_uri`, `prompt`, etc...) are correct and returns
|
298
|
+
# relevant information for rendering an OAuth Consent Screen.
|
299
|
+
#
|
300
|
+
# This endpoint returns:
|
301
|
+
# - A public representation of the Connected App requesting authorization
|
302
|
+
# - Whether _explicit_ consent must be granted before proceeding with the authorization
|
303
|
+
# - A list of scopes the Member has the ability to grant the Connected App
|
304
|
+
#
|
305
|
+
# Use this response to prompt the Member for consent (if necessary) before calling the [Submit OAuth Authorization](https://stytch.com/docs/b2b/api/connected-apps-oauth-authorize) endpoint.
|
306
|
+
#
|
307
|
+
# Exactly one of the following must be provided to identify the Member granting authorization:
|
308
|
+
# - `organization_id` + `member_id`
|
309
|
+
# - `session_token`
|
310
|
+
# - `session_jwt`
|
311
|
+
#
|
312
|
+
# If a `session_token` or `session_jwt` is passed, the OAuth Authorization will be linked to the Member's session for tracking purposes.
|
313
|
+
# One of these fields must be used if the Connected App intends to complete the [Exchange Access Token](https://stytch.com/docs/b2b/api/connected-app-access-token-exchange) flow.
|
314
|
+
#
|
315
|
+
# == Parameters:
|
316
|
+
# client_id::
|
317
|
+
# The ID of the Connected App client.
|
318
|
+
# The type of this field is +String+.
|
319
|
+
# redirect_uri::
|
320
|
+
# The callback URI used to redirect the user after authentication. This is the same URI provided at the start of the OAuth flow. This field is required when using the `authorization_code` grant.
|
321
|
+
# The type of this field is +String+.
|
322
|
+
# response_type::
|
323
|
+
# The OAuth 2.0 response type. For authorization code flows this value is `code`.
|
324
|
+
# The type of this field is +String+.
|
325
|
+
# scopes::
|
326
|
+
# An array of scopes requested by the client.
|
327
|
+
# The type of this field is list of +String+.
|
328
|
+
# organization_id::
|
329
|
+
# Globally unique UUID that identifies a specific Organization. The `organization_id` is critical to perform operations on an Organization, so be sure to preserve this value. You may also use the organization_slug or organization_external_id here as a convenience.
|
330
|
+
# The type of this field is nilable +String+.
|
331
|
+
# member_id::
|
332
|
+
# Globally unique UUID that identifies a specific Member. The `member_id` is critical to perform operations on a Member, so be sure to preserve this value. You may use an external_id here if one is set for the member.
|
333
|
+
# The type of this field is nilable +String+.
|
334
|
+
# session_token::
|
335
|
+
# A secret token for a given Stytch Session.
|
336
|
+
# The type of this field is nilable +String+.
|
337
|
+
# session_jwt::
|
338
|
+
# The JSON Web Token (JWT) for a given Stytch Session.
|
339
|
+
# The type of this field is nilable +String+.
|
340
|
+
# prompt::
|
341
|
+
# Space separated list that specifies how the Authorization Server should prompt the user for reauthentication and consent. Only `consent` is supported today.
|
342
|
+
# The type of this field is nilable +String+.
|
343
|
+
#
|
344
|
+
# == Returns:
|
345
|
+
# An object with the following fields:
|
346
|
+
# request_id::
|
347
|
+
# 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.
|
348
|
+
# The type of this field is +String+.
|
349
|
+
# member_id::
|
350
|
+
# Globally unique UUID that identifies a specific Member.
|
351
|
+
# The type of this field is +String+.
|
352
|
+
# member::
|
353
|
+
# The [Member object](https://stytch.com/docs/b2b/api/member-object)
|
354
|
+
# The type of this field is +Member+ (+object+).
|
355
|
+
# organization::
|
356
|
+
# The [Organization object](https://stytch.com/docs/b2b/api/organization-object).
|
357
|
+
# The type of this field is +Organization+ (+object+).
|
358
|
+
# client::
|
359
|
+
# (no documentation yet)
|
360
|
+
# The type of this field is +ConnectedAppPublic+ (+object+).
|
361
|
+
# consent_required::
|
362
|
+
# Whether the user must provide explicit consent for the authorization request.
|
363
|
+
# The type of this field is +Boolean+.
|
364
|
+
# scope_results::
|
365
|
+
# Details about each requested scope.
|
366
|
+
# The type of this field is list of +ScopeResult+ (+object+).
|
367
|
+
# status_code::
|
368
|
+
# (no documentation yet)
|
369
|
+
# The type of this field is +Integer+.
|
370
|
+
def authorize_start(
|
371
|
+
client_id:,
|
372
|
+
redirect_uri:,
|
373
|
+
response_type:,
|
374
|
+
scopes:,
|
375
|
+
organization_id: nil,
|
376
|
+
member_id: nil,
|
377
|
+
session_token: nil,
|
378
|
+
session_jwt: nil,
|
379
|
+
prompt: nil
|
380
|
+
)
|
381
|
+
headers = {}
|
382
|
+
request = {
|
383
|
+
client_id: client_id,
|
384
|
+
redirect_uri: redirect_uri,
|
385
|
+
response_type: response_type,
|
386
|
+
scopes: scopes
|
387
|
+
}
|
388
|
+
request[:organization_id] = organization_id unless organization_id.nil?
|
389
|
+
request[:member_id] = member_id unless member_id.nil?
|
390
|
+
request[:session_token] = session_token unless session_token.nil?
|
391
|
+
request[:session_jwt] = session_jwt unless session_jwt.nil?
|
392
|
+
request[:prompt] = prompt unless prompt.nil?
|
393
|
+
|
394
|
+
post_request('/v1/b2b/idp/oauth/authorize/start', request, headers)
|
395
|
+
end
|
396
|
+
|
397
|
+
# Completes a request for authorization of a Connected App to access a Member's account.
|
398
|
+
#
|
399
|
+
# Call this endpoint using the query parameters from an OAuth Authorization request, after previously validating those parameters using the
|
400
|
+
# [Preflight Check](https://stytch.com/docs/b2b/api/connected-apps-oauth-authorize-start) API.
|
401
|
+
# Note that this endpoint takes in a few additional parameters the preflight check does not- `state`, `nonce`, and `code_challenge`.
|
402
|
+
#
|
403
|
+
# If the authorization was successful, the `redirect_uri` will contain a valid `authorization_code` embedded as a query parameter.
|
404
|
+
# If the authorization was unsuccessful, the `redirect_uri` will contain an OAuth2.1 `error_code`.
|
405
|
+
# In both cases, redirect the Member to the location for the response to be consumed by the Connected App.
|
406
|
+
#
|
407
|
+
# Exactly one of the following must be provided to identify the Member granting authorization:
|
408
|
+
# - `organization_id` + `member_id`
|
409
|
+
# - `session_token`
|
410
|
+
# - `session_jwt`
|
411
|
+
#
|
412
|
+
# If a `session_token` or `session_jwt` is passed, the OAuth Authorization will be linked to the Member's session for tracking purposes.
|
413
|
+
# One of these fields must be used if the Connected App intends to complete the [Exchange Access Token](https://stytch.com/docs/b2b/api/connected-app-access-token-exchange) flow.
|
414
|
+
#
|
415
|
+
# == Parameters:
|
416
|
+
# consent_granted::
|
417
|
+
# Indicates whether the user granted the requested scopes.
|
418
|
+
# The type of this field is +Boolean+.
|
419
|
+
# scopes::
|
420
|
+
# An array of scopes requested by the client.
|
421
|
+
# The type of this field is list of +String+.
|
422
|
+
# client_id::
|
423
|
+
# The ID of the Connected App client.
|
424
|
+
# The type of this field is +String+.
|
425
|
+
# redirect_uri::
|
426
|
+
# The callback URI used to redirect the user after authentication. This is the same URI provided at the start of the OAuth flow. This field is required when using the `authorization_code` grant.
|
427
|
+
# The type of this field is +String+.
|
428
|
+
# response_type::
|
429
|
+
# The OAuth 2.0 response type. For authorization code flows this value is `code`.
|
430
|
+
# The type of this field is +String+.
|
431
|
+
# organization_id::
|
432
|
+
# Globally unique UUID that identifies a specific Organization. The `organization_id` is critical to perform operations on an Organization, so be sure to preserve this value. You may also use the organization_slug or organization_external_id here as a convenience.
|
433
|
+
# The type of this field is nilable +String+.
|
434
|
+
# member_id::
|
435
|
+
# Globally unique UUID that identifies a specific Member. The `member_id` is critical to perform operations on a Member, so be sure to preserve this value. You may use an external_id here if one is set for the member.
|
436
|
+
# The type of this field is nilable +String+.
|
437
|
+
# session_token::
|
438
|
+
# A secret token for a given Stytch Session.
|
439
|
+
# The type of this field is nilable +String+.
|
440
|
+
# session_jwt::
|
441
|
+
# The JSON Web Token (JWT) for a given Stytch Session.
|
442
|
+
# The type of this field is nilable +String+.
|
443
|
+
# prompt::
|
444
|
+
# Space separated list that specifies how the Authorization Server should prompt the user for reauthentication and consent. Only `consent` is supported today.
|
445
|
+
# The type of this field is nilable +String+.
|
446
|
+
# state::
|
447
|
+
# An opaque value used to maintain state between the request and callback.
|
448
|
+
# The type of this field is nilable +String+.
|
449
|
+
# nonce::
|
450
|
+
# A string used to associate a client session with an ID token to mitigate replay attacks.
|
451
|
+
# The type of this field is nilable +String+.
|
452
|
+
# code_challenge::
|
453
|
+
# A base64url encoded challenge derived from the code verifier for PKCE flows.
|
454
|
+
# The type of this field is nilable +String+.
|
455
|
+
#
|
456
|
+
# == Returns:
|
457
|
+
# An object with the following fields:
|
458
|
+
# request_id::
|
459
|
+
# 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.
|
460
|
+
# The type of this field is +String+.
|
461
|
+
# redirect_uri::
|
462
|
+
# The callback URI used to redirect the user after authentication. This is the same URI provided at the start of the OAuth flow. This field is required when using the `authorization_code` grant.
|
463
|
+
# The type of this field is +String+.
|
464
|
+
# status_code::
|
465
|
+
# (no documentation yet)
|
466
|
+
# The type of this field is +Integer+.
|
467
|
+
# authorization_code::
|
468
|
+
# A one-time use code that can be exchanged for tokens.
|
469
|
+
# The type of this field is nilable +String+.
|
470
|
+
def authorize(
|
471
|
+
consent_granted:,
|
472
|
+
scopes:,
|
473
|
+
client_id:,
|
474
|
+
redirect_uri:,
|
475
|
+
response_type:,
|
476
|
+
organization_id: nil,
|
477
|
+
member_id: nil,
|
478
|
+
session_token: nil,
|
479
|
+
session_jwt: nil,
|
480
|
+
prompt: nil,
|
481
|
+
state: nil,
|
482
|
+
nonce: nil,
|
483
|
+
code_challenge: nil
|
484
|
+
)
|
485
|
+
headers = {}
|
486
|
+
request = {
|
487
|
+
consent_granted: consent_granted,
|
488
|
+
scopes: scopes,
|
489
|
+
client_id: client_id,
|
490
|
+
redirect_uri: redirect_uri,
|
491
|
+
response_type: response_type
|
492
|
+
}
|
493
|
+
request[:organization_id] = organization_id unless organization_id.nil?
|
494
|
+
request[:member_id] = member_id unless member_id.nil?
|
495
|
+
request[:session_token] = session_token unless session_token.nil?
|
496
|
+
request[:session_jwt] = session_jwt unless session_jwt.nil?
|
497
|
+
request[:prompt] = prompt unless prompt.nil?
|
498
|
+
request[:state] = state unless state.nil?
|
499
|
+
request[:nonce] = nonce unless nonce.nil?
|
500
|
+
request[:code_challenge] = code_challenge unless code_challenge.nil?
|
501
|
+
|
502
|
+
post_request('/v1/b2b/idp/oauth/authorize', request, headers)
|
503
|
+
end
|
504
|
+
end
|
265
505
|
end
|
266
506
|
end
|
@@ -993,7 +993,7 @@ module StytchB2B
|
|
993
993
|
# If this field is provided and a session header is passed into the request, the Member Session must have permission to perform the `update.info.untrusted-metadata` action on the `stytch.member` Resource. Alternatively, if the Member Session matches the Member associated with the `member_id` passed in the request, the authorization check will also allow a Member Session that has permission to perform the `update.info.untrusted-metadata` action on the `stytch.self` Resource.
|
994
994
|
# The type of this field is nilable +object+.
|
995
995
|
# is_breakglass::
|
996
|
-
# Identifies the Member as a break glass user - someone who has permissions to authenticate into an Organization by bypassing the Organization's settings. A break glass account is typically used for emergency purposes to gain access outside of normal authentication procedures. Refer to the [Organization object](organization-object) and its `auth_methods` and `allowed_auth_methods` fields for more details.
|
996
|
+
# Identifies the Member as a break glass user - someone who has permissions to authenticate into an Organization by bypassing the Organization's settings. A break glass account is typically used for emergency purposes to gain access outside of normal authentication procedures. Refer to the [Organization object](https://stytch.com/docs/b2b/api/organization-object) and its `auth_methods` and `allowed_auth_methods` fields for more details.
|
997
997
|
#
|
998
998
|
# If this field is provided and a session header is passed into the request, the Member Session must have permission to perform the `update.settings.is-breakglass` action on the `stytch.member` Resource.
|
999
999
|
# The type of this field is nilable +Boolean+.
|
@@ -1030,14 +1030,14 @@ module StytchB2B
|
|
1030
1030
|
# If this field is provided and a session header is passed into the request, the Member Session must have permission to perform the `update.settings.default-mfa-method` action on the `stytch.member` Resource. Alternatively, if the Member Session matches the Member associated with the `member_id` passed in the request, the authorization check will also allow a Member Session that has permission to perform the `update.settings.default-mfa-method` action on the `stytch.self` Resource.
|
1031
1031
|
# The type of this field is nilable +String+.
|
1032
1032
|
# email_address::
|
1033
|
-
# Updates the Member's `email_address`, if provided.
|
1033
|
+
# Updates the Member's `email_address`, if provided. This will clear any existing passwords and require re-verification of the new email address.
|
1034
1034
|
# If a Member's email address is changed, other Members in the same Organization cannot use the old email address, although the Member may update back to their old email address.
|
1035
1035
|
# A Member's email address can only be useable again by other Members if the Member is deleted.
|
1036
1036
|
#
|
1037
1037
|
# If this field is provided and a session header is passed into the request, the Member Session must have permission to perform the `update.info.email` action on the `stytch.member` Resource. Members cannot update their own email address.
|
1038
1038
|
# The type of this field is nilable +String+.
|
1039
1039
|
# external_id::
|
1040
|
-
# An identifier that can be used in API calls
|
1040
|
+
# An identifier that can be used in most API calls where a `member_id` is expected. This is a string consisting of alphanumeric, `.`, `_`, `-`, or `|` characters with a maximum length of 128 characters. External IDs must be unique within an organization, but may be reused across different organizations in the same project.
|
1041
1041
|
# The type of this field is nilable +String+.
|
1042
1042
|
# unlink_email::
|
1043
1043
|
# If `unlink_email` is `true` and an `email_address` is provided, the Member's previous email will be deleted instead of retired. Defaults to `false`.
|
@@ -1135,12 +1135,14 @@ module StytchB2B
|
|
1135
1135
|
|
1136
1136
|
# Reactivates a deleted Member's status and its associated email status (if applicable) to active, specified by `organization_id` and `member_id`. This endpoint will only work for Members with at least one verified email where their `email_address_verified` is `true`.
|
1137
1137
|
#
|
1138
|
+
# Note that this endpoint does not accept an `external_id`. The Stytch `member_id` must be provided.
|
1139
|
+
#
|
1138
1140
|
# == Parameters:
|
1139
1141
|
# organization_id::
|
1140
1142
|
# Globally unique UUID that identifies a specific Organization. The `organization_id` is critical to perform operations on an Organization, so be sure to preserve this value. You may also use the organization_slug or organization_external_id here as a convenience.
|
1141
1143
|
# The type of this field is +String+.
|
1142
1144
|
# member_id::
|
1143
|
-
# Globally unique UUID that identifies a specific Member. The `member_id` is critical to perform operations on a Member, so be sure to preserve this value.
|
1145
|
+
# Globally unique UUID that identifies a specific Member. The `member_id` is critical to perform operations on a Member, so be sure to preserve this value.
|
1144
1146
|
# The type of this field is +String+.
|
1145
1147
|
#
|
1146
1148
|
# == Returns:
|
@@ -1292,7 +1294,7 @@ module StytchB2B
|
|
1292
1294
|
# 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.
|
1293
1295
|
# The type of this field is +String+.
|
1294
1296
|
# members::
|
1295
|
-
# An array of [Member objects](member-object).
|
1297
|
+
# An array of [Member objects](https://stytch.com/docs/b2b/api/member-object).
|
1296
1298
|
# The type of this field is list of +Member+ (+object+).
|
1297
1299
|
# results_metadata::
|
1298
1300
|
# The search `results_metadata` object contains metadata relevant to your specific query like `total` and `next_cursor`.
|
@@ -1658,7 +1660,7 @@ module StytchB2B
|
|
1658
1660
|
# Flag for whether or not to save a Member as `pending` or `active` in Stytch. It defaults to false. If true, new Members will be created with status `pending` in Stytch's backend. Their status will remain `pending` and they will continue to receive signup email templates for every Email Magic Link until that Member authenticates and becomes `active`. If false, new Members will be created with status `active`.
|
1659
1661
|
# The type of this field is nilable +Boolean+.
|
1660
1662
|
# is_breakglass::
|
1661
|
-
# Identifies the Member as a break glass user - someone who has permissions to authenticate into an Organization by bypassing the Organization's settings. A break glass account is typically used for emergency purposes to gain access outside of normal authentication procedures. Refer to the [Organization object](organization-object) and its `auth_methods` and `allowed_auth_methods` fields for more details.
|
1663
|
+
# Identifies the Member as a break glass user - someone who has permissions to authenticate into an Organization by bypassing the Organization's settings. A break glass account is typically used for emergency purposes to gain access outside of normal authentication procedures. Refer to the [Organization object](https://stytch.com/docs/b2b/api/organization-object) and its `auth_methods` and `allowed_auth_methods` fields for more details.
|
1662
1664
|
# The type of this field is nilable +Boolean+.
|
1663
1665
|
# mfa_phone_number::
|
1664
1666
|
# The Member's phone number. A Member may only have one phone number. The phone number should be in E.164 format (i.e. +1XXXXXXXXXX).
|
@@ -1671,7 +1673,7 @@ module StytchB2B
|
|
1671
1673
|
# for more information about role assignment.
|
1672
1674
|
# The type of this field is nilable list of +String+.
|
1673
1675
|
# external_id::
|
1674
|
-
# An identifier that can be used in API calls
|
1676
|
+
# An identifier that can be used in most API calls where a `member_id` is expected. This is a string consisting of alphanumeric, `.`, `_`, `-`, or `|` characters with a maximum length of 128 characters. External IDs must be unique within an organization, but may be reused across different organizations in the same project.
|
1675
1677
|
# The type of this field is nilable +String+.
|
1676
1678
|
#
|
1677
1679
|
# == Returns:
|
data/lib/stytch/b2b_passwords.rb
CHANGED
@@ -51,8 +51,8 @@ module StytchB2B
|
|
51
51
|
# The type of this field is +String+.
|
52
52
|
# valid_password::
|
53
53
|
# Returns `true` if the password passes our password validation. We offer two validation options,
|
54
|
-
# [zxcvbn](https://stytch.com/docs/passwords
|
55
|
-
# We also offer [LUDS](https://stytch.com/docs/passwords
|
54
|
+
# [zxcvbn](https://stytch.com/docs/guides/passwords/strength-policy) is the default option which offers a high level of sophistication.
|
55
|
+
# We also offer [LUDS](https://stytch.com/docs/b2b/guides/passwords/strength-policy). If an email address is included in the call we also
|
56
56
|
# require that the password hasn't been compromised using built-in breach detection powered by [HaveIBeenPwned](https://haveibeenpwned.com/)
|
57
57
|
# The type of this field is +Boolean+.
|
58
58
|
# score::
|
@@ -73,10 +73,10 @@ module StytchB2B
|
|
73
73
|
# The HTTP status code of the response. Stytch follows standard HTTP response status code patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX are server errors.
|
74
74
|
# The type of this field is +Integer+.
|
75
75
|
# luds_feedback::
|
76
|
-
# Feedback for how to improve the password's strength using [luds](https://stytch.com/docs/passwords
|
76
|
+
# Feedback for how to improve the password's strength using [luds](https://stytch.com/docs/guides/passwords/strength-policy).
|
77
77
|
# The type of this field is nilable +LudsFeedback+ (+object+).
|
78
78
|
# zxcvbn_feedback::
|
79
|
-
# Feedback for how to improve the password's strength using [zxcvbn](https://stytch.com/docs/passwords
|
79
|
+
# Feedback for how to improve the password's strength using [zxcvbn](https://stytch.com/docs/b2b/guides/passwords/strength-policy).
|
80
80
|
# The type of this field is nilable +ZxcvbnFeedback+ (+object+).
|
81
81
|
def strength_check(
|
82
82
|
password:,
|
@@ -91,6 +91,9 @@ module StytchB2B
|
|
91
91
|
post_request('/v1/b2b/passwords/strength_check', request, headers)
|
92
92
|
end
|
93
93
|
|
94
|
+
#
|
95
|
+
# **Warning:** This endpoint marks the Member's email address as verified. Do **not** use this endpoint unless the user has already verified their email address in your application.
|
96
|
+
#
|
94
97
|
# Adds an existing password to a Member's email that doesn't have a password yet.
|
95
98
|
#
|
96
99
|
# We support migrating members from passwords stored with bcrypt, scrypt, argon2, MD-5, SHA-1, and PBKDF2. This endpoint has a rate limit of 100 requests per second.
|
@@ -161,7 +164,7 @@ module StytchB2B
|
|
161
164
|
# the user owns the phone number in question.
|
162
165
|
# The type of this field is nilable +Boolean+.
|
163
166
|
# external_id::
|
164
|
-
# If a new member is created, this will set an identifier that can be used in API calls
|
167
|
+
# If a new member is created, this will set an identifier that can be used in most API calls where a `member_id` is expected. This is a string consisting of alphanumeric, `.`, `_`, `-`, or `|` characters with a maximum length of 128 characters. External IDs must be unique within an organization, but may be reused across different organizations in the same project. Note that if a member already exists, this field will be ignored.
|
165
168
|
# The type of this field is nilable +String+.
|
166
169
|
#
|
167
170
|
# == Returns:
|
@@ -229,7 +232,7 @@ module StytchB2B
|
|
229
232
|
|
230
233
|
# Authenticate a member with their email address and password. This endpoint verifies that the member has a password currently set, and that the entered password is correct.
|
231
234
|
#
|
232
|
-
# If you have breach detection during authentication enabled in your [password strength policy](https://stytch.com/docs/b2b/guides/passwords/strength-
|
235
|
+
# If you have breach detection during authentication enabled in your [password strength policy](https://stytch.com/docs/b2b/guides/passwords/strength-policy) and the member's credentials have appeared in the HaveIBeenPwned dataset, this endpoint will return a `member_reset_password` error even if the member enters a correct password. We force a password reset in this case to ensure that the member is the legitimate owner of the email address and not a malicious actor abusing the compromised credentials.
|
233
236
|
#
|
234
237
|
# If the Member is required to complete MFA to log in to the Organization, the returned value of `member_authenticated` will be `false`, and an `intermediate_session_token` will be returned.
|
235
238
|
# The `intermediate_session_token` can be passed into the [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms) to complete the MFA step and acquire a full member session.
|
@@ -950,7 +953,7 @@ module StytchB2B
|
|
950
953
|
|
951
954
|
# Authenticate an email/password combination in the discovery flow. This authenticate flow is only valid for cross-org passwords use cases, and is not tied to a specific organization.
|
952
955
|
#
|
953
|
-
# If you have breach detection during authentication enabled in your [password strength policy](https://stytch.com/docs/b2b/guides/passwords/strength-
|
956
|
+
# If you have breach detection during authentication enabled in your [password strength policy](https://stytch.com/docs/b2b/guides/passwords/strength-policy) and the member's credentials have appeared in the HaveIBeenPwned dataset, this endpoint will return a `member_reset_password` error even if the member enters a correct password. We force a password reset in this case to ensure that the member is the legitimate owner of the email address and not a malicious actor abusing the compromised credentials.
|
954
957
|
#
|
955
958
|
# If successful, this endpoint will create a new intermediate session and return a list of discovered organizations that can be session exchanged into.
|
956
959
|
#
|
data/lib/stytch/b2b_sessions.rb
CHANGED
@@ -436,15 +436,15 @@ module StytchB2B
|
|
436
436
|
# Exchange an auth token issued by a trusted identity provider for a Stytch session. You must first register a Trusted Auth Token profile in the Stytch dashboard [here](https://stytch.com/dashboard/trusted-auth-tokens). If a session token or session JWT is provided, it will add the trusted auth token as an authentication factor to the existing session.
|
437
437
|
#
|
438
438
|
# == Parameters:
|
439
|
-
# organization_id::
|
440
|
-
# The organization ID that the session should be authenticated in.
|
441
|
-
# The type of this field is +String+.
|
442
439
|
# profile_id::
|
443
440
|
# The ID of the trusted auth token profile to use for attestation.
|
444
441
|
# The type of this field is +String+.
|
445
442
|
# token::
|
446
|
-
# The trusted auth token to authenticate.
|
443
|
+
# The trusted auth token to authenticate. The token must have an organization ID claim if JIT provisioning is enabled.
|
447
444
|
# The type of this field is +String+.
|
445
|
+
# organization_id::
|
446
|
+
# The organization ID that the session should be authenticated in. Must be provided if the trusted auth token does not have an organization ID claim.
|
447
|
+
# The type of this field is nilable +String+.
|
448
448
|
# session_duration_minutes::
|
449
449
|
# Set the session lifetime to be this many minutes from now. This will start a new session if one doesn't already exist,
|
450
450
|
# returning both an opaque `session_token` and `session_jwt` for this session. Remember that the `session_jwt` will have a fixed lifetime of
|
@@ -503,9 +503,9 @@ module StytchB2B
|
|
503
503
|
# If a valid `telemetry_id` was passed in the request and the [Fingerprint Lookup API](https://stytch.com/docs/fraud/api/fingerprint-lookup) returned results, the `member_device` response field will contain information about the member's device attributes.
|
504
504
|
# The type of this field is nilable +DeviceInfo+ (+object+).
|
505
505
|
def attest(
|
506
|
-
organization_id:,
|
507
506
|
profile_id:,
|
508
507
|
token:,
|
508
|
+
organization_id: nil,
|
509
509
|
session_duration_minutes: nil,
|
510
510
|
session_custom_claims: nil,
|
511
511
|
session_token: nil,
|
@@ -514,10 +514,10 @@ module StytchB2B
|
|
514
514
|
)
|
515
515
|
headers = {}
|
516
516
|
request = {
|
517
|
-
organization_id: organization_id,
|
518
517
|
profile_id: profile_id,
|
519
518
|
token: token
|
520
519
|
}
|
520
|
+
request[:organization_id] = organization_id unless organization_id.nil?
|
521
521
|
request[:session_duration_minutes] = session_duration_minutes unless session_duration_minutes.nil?
|
522
522
|
request[:session_custom_claims] = session_custom_claims unless session_custom_claims.nil?
|
523
523
|
request[:session_token] = session_token unless session_token.nil?
|
data/lib/stytch/b2b_sso.rb
CHANGED
@@ -546,6 +546,25 @@ module StytchB2B
|
|
546
546
|
end
|
547
547
|
end
|
548
548
|
|
549
|
+
class DeleteEncryptionPrivateKeyRequestOptions
|
550
|
+
# Optional authorization object.
|
551
|
+
# Pass in an active Stytch Member session token or session JWT and the request
|
552
|
+
# will be run using that member's permissions.
|
553
|
+
attr_accessor :authorization
|
554
|
+
|
555
|
+
def initialize(
|
556
|
+
authorization: nil
|
557
|
+
)
|
558
|
+
@authorization = authorization
|
559
|
+
end
|
560
|
+
|
561
|
+
def to_headers
|
562
|
+
headers = {}
|
563
|
+
headers.merge!(@authorization.to_headers) if authorization
|
564
|
+
headers
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
549
568
|
include Stytch::RequestHelper
|
550
569
|
|
551
570
|
def initialize(connection)
|
@@ -656,6 +675,9 @@ module StytchB2B
|
|
656
675
|
# idp_initiated_auth_disabled::
|
657
676
|
# Determines whether IDP initiated auth is allowed for a given SAML connection. Defaults to false (IDP Initiated Auth is enabled).
|
658
677
|
# The type of this field is nilable +Boolean+.
|
678
|
+
# saml_encryption_private_key::
|
679
|
+
# A PKCS1 format RSA private key used to decrypt encrypted SAML assertions. Only PKCS1 format (starting with "-----BEGIN RSA PRIVATE KEY-----") is supported.
|
680
|
+
# The type of this field is nilable +String+.
|
659
681
|
#
|
660
682
|
# == Returns:
|
661
683
|
# An object with the following fields:
|
@@ -687,6 +709,7 @@ module StytchB2B
|
|
687
709
|
nameid_format: nil,
|
688
710
|
alternative_acs_url: nil,
|
689
711
|
idp_initiated_auth_disabled: nil,
|
712
|
+
saml_encryption_private_key: nil,
|
690
713
|
method_options: nil
|
691
714
|
)
|
692
715
|
headers = {}
|
@@ -705,6 +728,7 @@ module StytchB2B
|
|
705
728
|
request[:nameid_format] = nameid_format unless nameid_format.nil?
|
706
729
|
request[:alternative_acs_url] = alternative_acs_url unless alternative_acs_url.nil?
|
707
730
|
request[:idp_initiated_auth_disabled] = idp_initiated_auth_disabled unless idp_initiated_auth_disabled.nil?
|
731
|
+
request[:saml_encryption_private_key] = saml_encryption_private_key unless saml_encryption_private_key.nil?
|
708
732
|
|
709
733
|
put_request("/v1/b2b/sso/saml/#{organization_id}/connections/#{connection_id}", request, headers)
|
710
734
|
end
|
@@ -796,6 +820,44 @@ module StytchB2B
|
|
796
820
|
headers = headers.merge(method_options.to_headers) unless method_options.nil?
|
797
821
|
delete_request("/v1/b2b/sso/saml/#{organization_id}/connections/#{connection_id}/verification_certificates/#{certificate_id}", headers)
|
798
822
|
end
|
823
|
+
|
824
|
+
# Delete a SAML encryption private key.
|
825
|
+
#
|
826
|
+
# == Parameters:
|
827
|
+
# organization_id::
|
828
|
+
# Globally unique UUID that identifies a specific Organization. The `organization_id` is critical to perform operations on an Organization, so be sure to preserve this value. You may also use the organization_slug or organization_external_id here as a convenience.
|
829
|
+
# The type of this field is +String+.
|
830
|
+
# connection_id::
|
831
|
+
# Globally unique UUID that identifies a specific SSO `connection_id` for a Member.
|
832
|
+
# The type of this field is +String+.
|
833
|
+
# private_key_id::
|
834
|
+
# The ID of the encryption private key to be deleted.
|
835
|
+
# The type of this field is +String+.
|
836
|
+
#
|
837
|
+
# == Returns:
|
838
|
+
# An object with the following fields:
|
839
|
+
# request_id::
|
840
|
+
# 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.
|
841
|
+
# The type of this field is +String+.
|
842
|
+
# private_key_id::
|
843
|
+
# The ID of the encryption private key.
|
844
|
+
# The type of this field is +String+.
|
845
|
+
# status_code::
|
846
|
+
# The HTTP status code of the response. Stytch follows standard HTTP response status code patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX are server errors.
|
847
|
+
# The type of this field is +Integer+.
|
848
|
+
#
|
849
|
+
# == Method Options:
|
850
|
+
# This method supports an optional +StytchB2B::SSO::SAML::DeleteEncryptionPrivateKeyRequestOptions+ object which will modify the headers sent in the HTTP request.
|
851
|
+
def delete_encryption_private_key(
|
852
|
+
organization_id:,
|
853
|
+
connection_id:,
|
854
|
+
private_key_id:,
|
855
|
+
method_options: nil
|
856
|
+
)
|
857
|
+
headers = {}
|
858
|
+
headers = headers.merge(method_options.to_headers) unless method_options.nil?
|
859
|
+
delete_request("/v1/b2b/sso/saml/#{organization_id}/connections/#{connection_id}/encryption_private_keys/#{private_key_id}", headers)
|
860
|
+
end
|
799
861
|
end
|
800
862
|
|
801
863
|
class External
|
data/lib/stytch/client.rb
CHANGED
@@ -28,7 +28,7 @@ module Stytch
|
|
28
28
|
class Client
|
29
29
|
ENVIRONMENTS = %i[live test].freeze
|
30
30
|
|
31
|
-
attr_reader :connected_app, :crypto_wallets, :fraud, :impersonation, :m2m, :magic_links, :oauth, :otps, :passwords, :project, :rbac, :sessions, :totps, :users, :webauthn
|
31
|
+
attr_reader :connected_app, :crypto_wallets, :fraud, :idp, :impersonation, :m2m, :magic_links, :oauth, :otps, :passwords, :project, :rbac, :sessions, :totps, :users, :webauthn
|
32
32
|
|
33
33
|
def initialize(project_id:, secret:, env: nil, fraud_env: nil, &block)
|
34
34
|
@api_host = api_host(env, project_id)
|
@@ -41,11 +41,11 @@ module Stytch
|
|
41
41
|
|
42
42
|
rbac = Stytch::RBAC.new(@connection)
|
43
43
|
@policy_cache = Stytch::PolicyCache.new(rbac_client: rbac)
|
44
|
-
@idp = Stytch::IDP.new(@connection, @project_id, @policy_cache)
|
45
44
|
|
46
45
|
@connected_app = Stytch::ConnectedApp.new(@connection)
|
47
46
|
@crypto_wallets = Stytch::CryptoWallets.new(@connection)
|
48
47
|
@fraud = Stytch::Fraud.new(@fraud_connection)
|
48
|
+
@idp = Stytch::IDP.new(@connection, @project_id, @policy_cache)
|
49
49
|
@impersonation = Stytch::Impersonation.new(@connection)
|
50
50
|
@m2m = Stytch::M2M.new(@connection, @project_id, @is_b2b_client)
|
51
51
|
@magic_links = Stytch::MagicLinks.new(@connection)
|
@@ -202,21 +202,18 @@ module Stytch
|
|
202
202
|
# client_type::
|
203
203
|
# The type of Connected App. Supported values are `first_party`, `first_party_public`, `third_party`, and `third_party_public`.
|
204
204
|
# The type of this field is +CreateRequestClientType+ (string enum).
|
205
|
-
# redirect_urls::
|
206
|
-
# Array of redirect URI values for use in OAuth Authorization flows.
|
207
|
-
# The type of this field is list of +String+.
|
208
|
-
# full_access_allowed::
|
209
|
-
# Valid for first party clients only. If `true`, an authorization token granted to this Client can be exchanged for a full Stytch session.
|
210
|
-
# The type of this field is +Boolean+.
|
211
|
-
# post_logout_redirect_urls::
|
212
|
-
# Array of redirect URI values for use in OIDC Logout flows.
|
213
|
-
# The type of this field is list of +String+.
|
214
205
|
# client_name::
|
215
206
|
# A human-readable name for the client.
|
216
207
|
# The type of this field is nilable +String+.
|
217
208
|
# client_description::
|
218
209
|
# A human-readable description for the client.
|
219
210
|
# The type of this field is nilable +String+.
|
211
|
+
# redirect_urls::
|
212
|
+
# Array of redirect URI values for use in OAuth Authorization flows.
|
213
|
+
# The type of this field is nilable list of +String+.
|
214
|
+
# full_access_allowed::
|
215
|
+
# Valid for first party clients only. If `true`, an authorization token granted to this Client can be exchanged for a full Stytch session.
|
216
|
+
# The type of this field is nilable +Boolean+.
|
220
217
|
# access_token_expiry_minutes::
|
221
218
|
# The number of minutes before the access token expires. The default is 60 minutes.
|
222
219
|
# The type of this field is nilable +Integer+.
|
@@ -226,6 +223,9 @@ module Stytch
|
|
226
223
|
# access_token_template_content::
|
227
224
|
# The content of the access token custom claims template. The template must be a valid JSON object.
|
228
225
|
# The type of this field is nilable +String+.
|
226
|
+
# post_logout_redirect_urls::
|
227
|
+
# Array of redirect URI values for use in OIDC Logout flows.
|
228
|
+
# The type of this field is nilable list of +String+.
|
229
229
|
# logo_url::
|
230
230
|
# The logo URL of the Connected App, if any.
|
231
231
|
# The type of this field is nilable +String+.
|
@@ -246,29 +246,29 @@ module Stytch
|
|
246
246
|
# The type of this field is +Integer+.
|
247
247
|
def create(
|
248
248
|
client_type:,
|
249
|
-
redirect_urls:,
|
250
|
-
full_access_allowed:,
|
251
|
-
post_logout_redirect_urls:,
|
252
249
|
client_name: nil,
|
253
250
|
client_description: nil,
|
251
|
+
redirect_urls: nil,
|
252
|
+
full_access_allowed: nil,
|
254
253
|
access_token_expiry_minutes: nil,
|
255
254
|
access_token_custom_audience: nil,
|
256
255
|
access_token_template_content: nil,
|
256
|
+
post_logout_redirect_urls: nil,
|
257
257
|
logo_url: nil,
|
258
258
|
bypass_consent_for_offline_access: nil
|
259
259
|
)
|
260
260
|
headers = {}
|
261
261
|
request = {
|
262
|
-
client_type: client_type
|
263
|
-
redirect_urls: redirect_urls,
|
264
|
-
full_access_allowed: full_access_allowed,
|
265
|
-
post_logout_redirect_urls: post_logout_redirect_urls
|
262
|
+
client_type: client_type
|
266
263
|
}
|
267
264
|
request[:client_name] = client_name unless client_name.nil?
|
268
265
|
request[:client_description] = client_description unless client_description.nil?
|
266
|
+
request[:redirect_urls] = redirect_urls unless redirect_urls.nil?
|
267
|
+
request[:full_access_allowed] = full_access_allowed unless full_access_allowed.nil?
|
269
268
|
request[:access_token_expiry_minutes] = access_token_expiry_minutes unless access_token_expiry_minutes.nil?
|
270
269
|
request[:access_token_custom_audience] = access_token_custom_audience unless access_token_custom_audience.nil?
|
271
270
|
request[:access_token_template_content] = access_token_template_content unless access_token_template_content.nil?
|
271
|
+
request[:post_logout_redirect_urls] = post_logout_redirect_urls unless post_logout_redirect_urls.nil?
|
272
272
|
request[:logo_url] = logo_url unless logo_url.nil?
|
273
273
|
request[:bypass_consent_for_offline_access] = bypass_consent_for_offline_access unless bypass_consent_for_offline_access.nil?
|
274
274
|
|
data/lib/stytch/idp.rb
CHANGED
@@ -1,36 +1,46 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
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
|
+
|
3
9
|
require 'jwt'
|
4
10
|
require 'json/jwt'
|
5
11
|
require_relative 'errors'
|
6
12
|
require_relative 'request_helper'
|
7
|
-
require_relative 'rbac_local'
|
8
13
|
|
9
14
|
module Stytch
|
10
15
|
class IDP
|
11
16
|
include Stytch::RequestHelper
|
17
|
+
attr_reader :oauth
|
12
18
|
|
13
19
|
def initialize(connection, project_id, policy_cache)
|
14
20
|
@connection = connection
|
15
|
-
|
21
|
+
|
22
|
+
@oauth = Stytch::IDP::OAuth.new(@connection)
|
16
23
|
@policy_cache = policy_cache
|
17
|
-
@
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
token_type
|
31
|
-
]
|
24
|
+
@project_id = project_id
|
25
|
+
@cache_last_update = 0
|
26
|
+
@jwks_loader = lambda do |options|
|
27
|
+
@cached_keys = nil if options[:invalidate] && @cache_last_update < Time.now.to_i - 300
|
28
|
+
@cached_keys ||= begin
|
29
|
+
@cache_last_update = Time.now.to_i
|
30
|
+
keys = []
|
31
|
+
get_jwks(project_id: @project_id)['keys'].each do |r|
|
32
|
+
keys << r
|
33
|
+
end
|
34
|
+
{ keys: keys }
|
35
|
+
end
|
36
|
+
end
|
32
37
|
end
|
33
38
|
|
39
|
+
# MANUAL(IDP::introspect_token_network)(SERVICE_METHOD)
|
40
|
+
# ADDIMPORT: require 'jwt'
|
41
|
+
# ADDIMPORT: require 'json/jwt'
|
42
|
+
# ADDIMPORT: require_relative 'errors'
|
43
|
+
|
34
44
|
# Introspects a token JWT from an authorization code response.
|
35
45
|
# Access tokens are JWTs signed with the project's JWKs. Refresh tokens are opaque tokens.
|
36
46
|
# Access tokens contain a standard set of claims as well as any custom claims generated from templates.
|
@@ -102,7 +112,7 @@ module Stytch
|
|
102
112
|
jwt_response = res
|
103
113
|
return nil unless jwt_response['active']
|
104
114
|
|
105
|
-
custom_claims = res.reject { |k, _|
|
115
|
+
custom_claims = res.reject { |k, _| non_custom_claim_keys.include?(k) }
|
106
116
|
scope = jwt_response['scope']
|
107
117
|
|
108
118
|
if authorization_check
|
@@ -171,18 +181,6 @@ module Stytch
|
|
171
181
|
authorization_check: nil
|
172
182
|
)
|
173
183
|
scope_claim = 'scope'
|
174
|
-
|
175
|
-
# Create a JWKS loader similar to other classes in the codebase
|
176
|
-
@cache_last_update = 0
|
177
|
-
jwks_loader = lambda do |options|
|
178
|
-
@cached_keys = nil if options[:invalidate] && @cache_last_update < Time.now.to_i - 300
|
179
|
-
if @cached_keys.nil?
|
180
|
-
@cached_keys = get_jwks(project_id: @project_id)
|
181
|
-
@cache_last_update = Time.now.to_i
|
182
|
-
end
|
183
|
-
@cached_keys
|
184
|
-
end
|
185
|
-
|
186
184
|
begin
|
187
185
|
decoded_jwt = JWT.decode(
|
188
186
|
access_token,
|
@@ -190,14 +188,14 @@ module Stytch
|
|
190
188
|
true,
|
191
189
|
{
|
192
190
|
algorithms: ['RS256'],
|
193
|
-
jwks: jwks_loader,
|
191
|
+
jwks: @jwks_loader,
|
194
192
|
iss: ["stytch.com/#{@project_id}", @connection.url_prefix],
|
195
193
|
aud: @project_id
|
196
194
|
}
|
197
195
|
)[0]
|
198
196
|
|
199
197
|
generic_claims = decoded_jwt
|
200
|
-
custom_claims = generic_claims.reject { |k, _|
|
198
|
+
custom_claims = generic_claims.reject { |k, _| non_custom_claim_keys.include?(k) }
|
201
199
|
scope = generic_claims[scope_claim]
|
202
200
|
|
203
201
|
if authorization_check
|
@@ -231,6 +229,26 @@ module Stytch
|
|
231
229
|
end
|
232
230
|
end
|
233
231
|
|
232
|
+
private
|
233
|
+
|
234
|
+
def non_custom_claim_keys
|
235
|
+
%w[
|
236
|
+
aud
|
237
|
+
exp
|
238
|
+
iat
|
239
|
+
iss
|
240
|
+
jti
|
241
|
+
nbf
|
242
|
+
sub
|
243
|
+
active
|
244
|
+
client_id
|
245
|
+
request_id
|
246
|
+
scope
|
247
|
+
status_code
|
248
|
+
token_type
|
249
|
+
]
|
250
|
+
end
|
251
|
+
|
234
252
|
# Gets the JWKS for the project.
|
235
253
|
#
|
236
254
|
# == Parameters:
|
@@ -247,5 +265,213 @@ module Stytch
|
|
247
265
|
request = request_with_query_params("/v1/sessions/jwks/#{project_id}", query_params)
|
248
266
|
get_request(request, headers)
|
249
267
|
end
|
268
|
+
|
269
|
+
# ENDMANUAL(IDP::introspect_token_network)
|
270
|
+
|
271
|
+
class OAuth
|
272
|
+
include Stytch::RequestHelper
|
273
|
+
|
274
|
+
def initialize(connection)
|
275
|
+
@connection = connection
|
276
|
+
end
|
277
|
+
|
278
|
+
# Initiates a request for authorization of a Connected App to access a User's account.
|
279
|
+
#
|
280
|
+
# Call this endpoint using the query parameters from an OAuth Authorization request.
|
281
|
+
# This endpoint validates various fields (`scope`, `client_id`, `redirect_uri`, `prompt`, etc...) are correct and returns
|
282
|
+
# relevant information for rendering an OAuth Consent Screen.
|
283
|
+
#
|
284
|
+
# This endpoint returns:
|
285
|
+
# - A public representation of the Connected App requesting authorization
|
286
|
+
# - Whether _explicit_ user consent must be granted before proceeding with the authorization
|
287
|
+
# - A list of scopes the user has the ability to grant the Connected App
|
288
|
+
#
|
289
|
+
# Use this response to prompt the user for consent (if necessary) before calling the [Submit OAuth Authorization](https://stytch.com/docs/api/connected-apps-oauth-authorize) endpoint.
|
290
|
+
#
|
291
|
+
# Exactly one of the following must be provided to identify the user granting authorization:
|
292
|
+
# - `user_id`
|
293
|
+
# - `session_token`
|
294
|
+
# - `session_jwt`
|
295
|
+
#
|
296
|
+
# If a `session_token` or `session_jwt` is passed, the OAuth Authorization will be linked to the user's session for tracking purposes.
|
297
|
+
# One of these fields must be used if the Connected App intends to complete the [Exchange Access Token](https://stytch.com/docs/api/connected-app-access-token-exchange) flow.
|
298
|
+
#
|
299
|
+
# == Parameters:
|
300
|
+
# client_id::
|
301
|
+
# The ID of the Connected App client.
|
302
|
+
# The type of this field is +String+.
|
303
|
+
# redirect_uri::
|
304
|
+
# The callback URI used to redirect the user after authentication. This is the same URI provided at the start of the OAuth flow. This field is required when using the `authorization_code` grant.
|
305
|
+
# The type of this field is +String+.
|
306
|
+
# response_type::
|
307
|
+
# The OAuth 2.0 response type. For authorization code flows this value is `code`.
|
308
|
+
# The type of this field is +String+.
|
309
|
+
# scopes::
|
310
|
+
# An array of scopes requested by the client.
|
311
|
+
# The type of this field is list of +String+.
|
312
|
+
# user_id::
|
313
|
+
# The unique ID of a specific User. You may use an `external_id` here if one is set for the user.
|
314
|
+
# The type of this field is nilable +String+.
|
315
|
+
# session_token::
|
316
|
+
# The `session_token` associated with a User's existing Session.
|
317
|
+
# The type of this field is nilable +String+.
|
318
|
+
# session_jwt::
|
319
|
+
# The `session_jwt` associated with a User's existing Session.
|
320
|
+
# The type of this field is nilable +String+.
|
321
|
+
# prompt::
|
322
|
+
# Space separated list that specifies how the Authorization Server should prompt the user for reauthentication and consent. Only `consent` is supported today.
|
323
|
+
# The type of this field is nilable +String+.
|
324
|
+
#
|
325
|
+
# == Returns:
|
326
|
+
# An object with the following fields:
|
327
|
+
# request_id::
|
328
|
+
# 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.
|
329
|
+
# The type of this field is +String+.
|
330
|
+
# user_id::
|
331
|
+
# The unique ID of the affected User.
|
332
|
+
# The type of this field is +String+.
|
333
|
+
# user::
|
334
|
+
# 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.
|
335
|
+
# The type of this field is +User+ (+object+).
|
336
|
+
# client::
|
337
|
+
# (no documentation yet)
|
338
|
+
# The type of this field is +ConnectedAppPublic+ (+object+).
|
339
|
+
# consent_required::
|
340
|
+
# Whether the user must provide explicit consent for the authorization request.
|
341
|
+
# The type of this field is +Boolean+.
|
342
|
+
# scope_results::
|
343
|
+
# Details about each requested scope.
|
344
|
+
# The type of this field is list of +ScopeResult+ (+object+).
|
345
|
+
# status_code::
|
346
|
+
# (no documentation yet)
|
347
|
+
# The type of this field is +Integer+.
|
348
|
+
def authorize_start(
|
349
|
+
client_id:,
|
350
|
+
redirect_uri:,
|
351
|
+
response_type:,
|
352
|
+
scopes:,
|
353
|
+
user_id: nil,
|
354
|
+
session_token: nil,
|
355
|
+
session_jwt: nil,
|
356
|
+
prompt: nil
|
357
|
+
)
|
358
|
+
headers = {}
|
359
|
+
request = {
|
360
|
+
client_id: client_id,
|
361
|
+
redirect_uri: redirect_uri,
|
362
|
+
response_type: response_type,
|
363
|
+
scopes: scopes
|
364
|
+
}
|
365
|
+
request[:user_id] = user_id unless user_id.nil?
|
366
|
+
request[:session_token] = session_token unless session_token.nil?
|
367
|
+
request[:session_jwt] = session_jwt unless session_jwt.nil?
|
368
|
+
request[:prompt] = prompt unless prompt.nil?
|
369
|
+
|
370
|
+
post_request('/v1/idp/oauth/authorize/start', request, headers)
|
371
|
+
end
|
372
|
+
|
373
|
+
# Completes a request for authorization of a Connected App to access a User's account.
|
374
|
+
#
|
375
|
+
# Call this endpoint using the query parameters from an OAuth Authorization request, after previously validating those parameters using the
|
376
|
+
# [Preflight Check](https://stytch.com/docs/api/connected-apps-oauth-authorize-start) API.
|
377
|
+
# Note that this endpoint takes in a few additional parameters the preflight check does not- `state`, `nonce`, and `code_challenge`.
|
378
|
+
#
|
379
|
+
# If the authorization was successful, the `redirect_uri` will contain a valid `authorization_code` embedded as a query parameter.
|
380
|
+
# If the authorization was unsuccessful, the `redirect_uri` will contain an OAuth2.1 `error_code`.
|
381
|
+
# In both cases, redirect the user to the location for the response to be consumed by the Connected App.
|
382
|
+
#
|
383
|
+
# Exactly one of the following must be provided to identify the user granting authorization:
|
384
|
+
# - `user_id`
|
385
|
+
# - `session_token`
|
386
|
+
# - `session_jwt`
|
387
|
+
#
|
388
|
+
# If a `session_token` or `session_jwt` is passed, the OAuth Authorization will be linked to the user's session for tracking purposes.
|
389
|
+
# One of these fields must be used if the Connected App intends to complete the [Exchange Access Token](https://stytch.com/docs/api/connected-app-access-token-exchange) flow.
|
390
|
+
#
|
391
|
+
# == Parameters:
|
392
|
+
# consent_granted::
|
393
|
+
# Indicates whether the user granted the requested scopes.
|
394
|
+
# The type of this field is +Boolean+.
|
395
|
+
# scopes::
|
396
|
+
# An array of scopes requested by the client.
|
397
|
+
# The type of this field is list of +String+.
|
398
|
+
# client_id::
|
399
|
+
# The ID of the Connected App client.
|
400
|
+
# The type of this field is +String+.
|
401
|
+
# redirect_uri::
|
402
|
+
# The callback URI used to redirect the user after authentication. This is the same URI provided at the start of the OAuth flow. This field is required when using the `authorization_code` grant.
|
403
|
+
# The type of this field is +String+.
|
404
|
+
# response_type::
|
405
|
+
# The OAuth 2.0 response type. For authorization code flows this value is `code`.
|
406
|
+
# The type of this field is +String+.
|
407
|
+
# user_id::
|
408
|
+
# The unique ID of a specific User. You may use an `external_id` here if one is set for the user.
|
409
|
+
# The type of this field is nilable +String+.
|
410
|
+
# session_token::
|
411
|
+
# The `session_token` associated with a User's existing Session.
|
412
|
+
# The type of this field is nilable +String+.
|
413
|
+
# session_jwt::
|
414
|
+
# The `session_jwt` associated with a User's existing Session.
|
415
|
+
# The type of this field is nilable +String+.
|
416
|
+
# prompt::
|
417
|
+
# Space separated list that specifies how the Authorization Server should prompt the user for reauthentication and consent. Only `consent` is supported today.
|
418
|
+
# The type of this field is nilable +String+.
|
419
|
+
# state::
|
420
|
+
# An opaque value used to maintain state between the request and callback.
|
421
|
+
# The type of this field is nilable +String+.
|
422
|
+
# nonce::
|
423
|
+
# A string used to associate a client session with an ID token to mitigate replay attacks.
|
424
|
+
# The type of this field is nilable +String+.
|
425
|
+
# code_challenge::
|
426
|
+
# A base64url encoded challenge derived from the code verifier for PKCE flows.
|
427
|
+
# The type of this field is nilable +String+.
|
428
|
+
#
|
429
|
+
# == Returns:
|
430
|
+
# An object with the following fields:
|
431
|
+
# request_id::
|
432
|
+
# 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.
|
433
|
+
# The type of this field is +String+.
|
434
|
+
# redirect_uri::
|
435
|
+
# The callback URI used to redirect the user after authentication. This is the same URI provided at the start of the OAuth flow. This field is required when using the `authorization_code` grant.
|
436
|
+
# The type of this field is +String+.
|
437
|
+
# status_code::
|
438
|
+
# (no documentation yet)
|
439
|
+
# The type of this field is +Integer+.
|
440
|
+
# authorization_code::
|
441
|
+
# A one-time use code that can be exchanged for tokens.
|
442
|
+
# The type of this field is nilable +String+.
|
443
|
+
def authorize(
|
444
|
+
consent_granted:,
|
445
|
+
scopes:,
|
446
|
+
client_id:,
|
447
|
+
redirect_uri:,
|
448
|
+
response_type:,
|
449
|
+
user_id: nil,
|
450
|
+
session_token: nil,
|
451
|
+
session_jwt: nil,
|
452
|
+
prompt: nil,
|
453
|
+
state: nil,
|
454
|
+
nonce: nil,
|
455
|
+
code_challenge: nil
|
456
|
+
)
|
457
|
+
headers = {}
|
458
|
+
request = {
|
459
|
+
consent_granted: consent_granted,
|
460
|
+
scopes: scopes,
|
461
|
+
client_id: client_id,
|
462
|
+
redirect_uri: redirect_uri,
|
463
|
+
response_type: response_type
|
464
|
+
}
|
465
|
+
request[:user_id] = user_id unless user_id.nil?
|
466
|
+
request[:session_token] = session_token unless session_token.nil?
|
467
|
+
request[:session_jwt] = session_jwt unless session_jwt.nil?
|
468
|
+
request[:prompt] = prompt unless prompt.nil?
|
469
|
+
request[:state] = state unless state.nil?
|
470
|
+
request[:nonce] = nonce unless nonce.nil?
|
471
|
+
request[:code_challenge] = code_challenge unless code_challenge.nil?
|
472
|
+
|
473
|
+
post_request('/v1/idp/oauth/authorize', request, headers)
|
474
|
+
end
|
475
|
+
end
|
250
476
|
end
|
251
477
|
end
|
data/lib/stytch/passwords.rb
CHANGED
@@ -242,7 +242,7 @@ module Stytch
|
|
242
242
|
# 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.
|
243
243
|
# The type of this field is +String+.
|
244
244
|
# valid_password::
|
245
|
-
# Returns `true` if the password passes our password validation. We offer two validation options, [zxcvbn](https://stytch.com/docs/passwords
|
245
|
+
# Returns `true` if the password passes our password validation. We offer two validation options, [zxcvbn](https://stytch.com/docs/guides/passwords/strength-policy) is the default option which offers a high level of sophistication. We also offer [LUDS](https://stytch.com/docs/guides/passwords/strength-policy). If an email address is included in the call we also require that the password hasn't been compromised using built-in breach detection powered by [HaveIBeenPwned](https://haveibeenpwned.com/).
|
246
246
|
# The type of this field is +Boolean+.
|
247
247
|
# score::
|
248
248
|
# The score of the password determined by [zxcvbn](https://github.com/dropbox/zxcvbn). Values will be between 1 and 4, a 3 or greater is required to pass validation.
|
@@ -327,7 +327,8 @@ module Stytch
|
|
327
327
|
# If a new user is created, this will set an identifier that can be used in API calls wherever a user_id is expected. This is a string consisting of alphanumeric, `.`, `_`, `-`, or `|` characters with a maximum length of 128 characters.
|
328
328
|
# The type of this field is nilable +String+.
|
329
329
|
# roles::
|
330
|
-
#
|
330
|
+
# Roles to explicitly assign to this User.
|
331
|
+
# See the [RBAC guide](https://stytch.com/docs/guides/rbac/role-assignment) for more information about role assignment.
|
331
332
|
# The type of this field is nilable list of +String+.
|
332
333
|
#
|
333
334
|
# == Returns:
|
data/lib/stytch/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stytch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 10.
|
4
|
+
version: 10.30.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- stytch
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-08-
|
11
|
+
date: 2025-08-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|