stytch 6.4.0 → 7.2.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/.github/workflows/ruby.yml +13 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +21 -0
- data/DEVELOPMENT.md +5 -2
- data/README.md +1 -1
- data/lib/stytch/b2b_client.rb +13 -3
- data/lib/stytch/b2b_discovery.rb +41 -11
- data/lib/stytch/b2b_magic_links.rb +23 -7
- data/lib/stytch/b2b_oauth.rb +12 -2
- data/lib/stytch/b2b_organizations.rb +348 -47
- data/lib/stytch/b2b_otp.rb +35 -4
- data/lib/stytch/b2b_passwords.rb +92 -19
- data/lib/stytch/b2b_rbac.rb +47 -0
- data/lib/stytch/b2b_recovery_codes.rb +199 -0
- data/lib/stytch/b2b_sessions.rb +187 -7
- data/lib/stytch/b2b_sso.rb +172 -19
- data/lib/stytch/b2b_totps.rb +261 -0
- data/lib/stytch/client.rb +2 -2
- data/lib/stytch/crypto_wallets.rb +4 -2
- data/lib/stytch/errors.rb +14 -0
- data/lib/stytch/m2m.rb +16 -9
- data/lib/stytch/magic_links.rb +20 -12
- data/lib/stytch/method_options.rb +22 -0
- data/lib/stytch/oauth.rb +10 -4
- data/lib/stytch/otps.rb +26 -16
- data/lib/stytch/passwords.rb +62 -14
- data/lib/stytch/rbac_local.rb +58 -0
- data/lib/stytch/request_helper.rb +12 -8
- data/lib/stytch/sessions.rb +51 -28
- data/lib/stytch/totps.rb +9 -5
- data/lib/stytch/users.rb +30 -16
- data/lib/stytch/version.rb +1 -1
- data/lib/stytch/webauthn.rb +126 -24
- data/stytch.gemspec +2 -0
- metadata +36 -2
data/lib/stytch/b2b_sessions.rb
CHANGED
@@ -6,14 +6,32 @@
|
|
6
6
|
# or your changes may be overwritten later!
|
7
7
|
# !!!
|
8
8
|
|
9
|
+
require 'jwt'
|
10
|
+
require 'json/jwt'
|
11
|
+
require_relative 'errors'
|
9
12
|
require_relative 'request_helper'
|
10
13
|
|
11
14
|
module StytchB2B
|
12
15
|
class Sessions
|
13
16
|
include Stytch::RequestHelper
|
14
17
|
|
15
|
-
def initialize(connection)
|
18
|
+
def initialize(connection, project_id, policy_cache)
|
16
19
|
@connection = connection
|
20
|
+
|
21
|
+
@policy_cache = policy_cache
|
22
|
+
@project_id = project_id
|
23
|
+
@cache_last_update = 0
|
24
|
+
@jwks_loader = lambda do |options|
|
25
|
+
@cached_keys = nil if options[:invalidate] && @cache_last_update < Time.now.to_i - 300
|
26
|
+
@cached_keys ||= begin
|
27
|
+
@cache_last_update = Time.now.to_i
|
28
|
+
keys = []
|
29
|
+
get_jwks(project_id: @project_id)['keys'].each do |r|
|
30
|
+
keys << r
|
31
|
+
end
|
32
|
+
{ keys: keys }
|
33
|
+
end
|
34
|
+
end
|
17
35
|
end
|
18
36
|
|
19
37
|
# Retrieves all active Sessions for a Member.
|
@@ -41,18 +59,26 @@ module StytchB2B
|
|
41
59
|
organization_id:,
|
42
60
|
member_id:
|
43
61
|
)
|
62
|
+
headers = {}
|
44
63
|
query_params = {
|
45
64
|
organization_id: organization_id,
|
46
65
|
member_id: member_id
|
47
66
|
}
|
48
67
|
request = request_with_query_params('/v1/b2b/sessions', query_params)
|
49
|
-
get_request(request)
|
68
|
+
get_request(request, headers)
|
50
69
|
end
|
51
70
|
|
52
71
|
# Authenticates a Session and updates its lifetime by the specified `session_duration_minutes`. If the `session_duration_minutes` is not specified, a Session will not be extended. This endpoint requires either a `session_jwt` or `session_token` be included in the request. It will return an error if both are present.
|
53
72
|
#
|
54
73
|
# 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.
|
55
74
|
#
|
75
|
+
# If an `authorization_check` object is passed in, this method will also check if the Member is authorized to perform the given action on the given Resource in the specified Organization. A Member is authorized if their Member Session contains a Role, assigned [explicitly or implicitly](https://stytch.com/docs/b2b/guides/rbac/role-assignment), with adequate permissions.
|
76
|
+
# In addition, the `organization_id` passed in the authorization check must match the Member's Organization.
|
77
|
+
#
|
78
|
+
# If the Member is not authorized to perform the specified action on the specified Resource, or if the
|
79
|
+
# `organization_id` does not match the Member's Organization, a 403 error will be thrown.
|
80
|
+
# Otherwise, the response will contain a list of Roles that satisfied the authorization check.
|
81
|
+
#
|
56
82
|
# == Parameters:
|
57
83
|
# session_token::
|
58
84
|
# A secret token for a given Stytch Session.
|
@@ -78,6 +104,21 @@ module StytchB2B
|
|
78
104
|
# delete a key, supply a null value. Custom claims made with reserved claims (`iss`, `sub`, `aud`, `exp`, `nbf`, `iat`, `jti`) will be ignored.
|
79
105
|
# Total custom claims size cannot exceed four kilobytes.
|
80
106
|
# The type of this field is nilable +object+.
|
107
|
+
# authorization_check::
|
108
|
+
# If an `authorization_check` object is passed in, this endpoint will also check if the Member is
|
109
|
+
# authorized to perform the given action on the given Resource in the specified Organization. A Member is authorized if
|
110
|
+
# their Member Session contains a Role, assigned
|
111
|
+
# [explicitly or implicitly](https://stytch.com/docs/b2b/guides/rbac/role-assignment), with adequate permissions.
|
112
|
+
# In addition, the `organization_id` passed in the authorization check must match the Member's Organization.
|
113
|
+
#
|
114
|
+
# The Roles on the Member Session may differ from the Roles you see on the Member object - Roles that are implicitly
|
115
|
+
# assigned by SSO connection or SSO group will only be valid for a Member Session if there is at least one authentication
|
116
|
+
# factor on the Member Session from the specified SSO connection.
|
117
|
+
#
|
118
|
+
# If the Member is not authorized to perform the specified action on the specified Resource, or if the
|
119
|
+
# `organization_id` does not match the Member's Organization, a 403 error will be thrown.
|
120
|
+
# Otherwise, the response will contain a list of Roles that satisfied the authorization check.
|
121
|
+
# The type of this field is nilable +AuthorizationCheck+ (+object+).
|
81
122
|
#
|
82
123
|
# == Returns:
|
83
124
|
# An object with the following fields:
|
@@ -102,19 +143,26 @@ module StytchB2B
|
|
102
143
|
# status_code::
|
103
144
|
# 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.
|
104
145
|
# The type of this field is +Integer+.
|
146
|
+
# verdict::
|
147
|
+
# If an `authorization_check` is provided in the request and the check succeeds, this field will return
|
148
|
+
# the complete list of Roles that gave the Member permission to perform the specified action on the specified Resource.
|
149
|
+
# The type of this field is nilable +AuthorizationVerdict+ (+object+).
|
105
150
|
def authenticate(
|
106
151
|
session_token: nil,
|
107
152
|
session_duration_minutes: nil,
|
108
153
|
session_jwt: nil,
|
109
|
-
session_custom_claims: nil
|
154
|
+
session_custom_claims: nil,
|
155
|
+
authorization_check: nil
|
110
156
|
)
|
157
|
+
headers = {}
|
111
158
|
request = {}
|
112
159
|
request[:session_token] = session_token unless session_token.nil?
|
113
160
|
request[:session_duration_minutes] = session_duration_minutes unless session_duration_minutes.nil?
|
114
161
|
request[:session_jwt] = session_jwt unless session_jwt.nil?
|
115
162
|
request[:session_custom_claims] = session_custom_claims unless session_custom_claims.nil?
|
163
|
+
request[:authorization_check] = authorization_check unless authorization_check.nil?
|
116
164
|
|
117
|
-
post_request('/v1/b2b/sessions/authenticate', request)
|
165
|
+
post_request('/v1/b2b/sessions/authenticate', request, headers)
|
118
166
|
end
|
119
167
|
|
120
168
|
# Revoke a Session and immediately invalidate all its tokens. To revoke a specific Session, pass either the `member_session_id`, `session_token`, or `session_jwt`. To revoke all Sessions for a Member, pass the `member_id`.
|
@@ -147,13 +195,14 @@ module StytchB2B
|
|
147
195
|
session_jwt: nil,
|
148
196
|
member_id: nil
|
149
197
|
)
|
198
|
+
headers = {}
|
150
199
|
request = {}
|
151
200
|
request[:member_session_id] = member_session_id unless member_session_id.nil?
|
152
201
|
request[:session_token] = session_token unless session_token.nil?
|
153
202
|
request[:session_jwt] = session_jwt unless session_jwt.nil?
|
154
203
|
request[:member_id] = member_id unless member_id.nil?
|
155
204
|
|
156
|
-
post_request('/v1/b2b/sessions/revoke', request)
|
205
|
+
post_request('/v1/b2b/sessions/revoke', request, headers)
|
157
206
|
end
|
158
207
|
|
159
208
|
# Use this endpoint to exchange a Member's existing session for another session in a different Organization. This can be used to accept an invite, but not to create a new member via domain matching.
|
@@ -253,6 +302,7 @@ module StytchB2B
|
|
253
302
|
session_custom_claims: nil,
|
254
303
|
locale: nil
|
255
304
|
)
|
305
|
+
headers = {}
|
256
306
|
request = {
|
257
307
|
organization_id: organization_id
|
258
308
|
}
|
@@ -262,11 +312,19 @@ module StytchB2B
|
|
262
312
|
request[:session_custom_claims] = session_custom_claims unless session_custom_claims.nil?
|
263
313
|
request[:locale] = locale unless locale.nil?
|
264
314
|
|
265
|
-
post_request('/v1/b2b/sessions/exchange', request)
|
315
|
+
post_request('/v1/b2b/sessions/exchange', request, headers)
|
266
316
|
end
|
267
317
|
|
268
318
|
# Get the JSON Web Key Set (JWKS) for a project.
|
269
319
|
#
|
320
|
+
# 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.
|
321
|
+
#
|
322
|
+
# 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.
|
323
|
+
#
|
324
|
+
# If you're using one of our [backend SDKs](https://stytch.com/docs/b2b/sdks), the JWKS roll will be handled for you.
|
325
|
+
#
|
326
|
+
# 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.
|
327
|
+
#
|
270
328
|
# == Parameters:
|
271
329
|
# project_id::
|
272
330
|
# The `project_id` to get the JWKS for.
|
@@ -286,9 +344,131 @@ module StytchB2B
|
|
286
344
|
def get_jwks(
|
287
345
|
project_id:
|
288
346
|
)
|
347
|
+
headers = {}
|
289
348
|
query_params = {}
|
290
349
|
request = request_with_query_params("/v1/b2b/sessions/jwks/#{project_id}", query_params)
|
291
|
-
get_request(request)
|
350
|
+
get_request(request, headers)
|
351
|
+
end
|
352
|
+
|
353
|
+
# MANUAL(Sessions::authenticate_jwt)(SERVICE_METHOD)
|
354
|
+
# ADDIMPORT: require 'jwt'
|
355
|
+
# ADDIMPORT: require 'json/jwt'
|
356
|
+
# ADDIMPORT: require_relative 'errors'
|
357
|
+
|
358
|
+
# Parse a JWT and verify the signature. If max_token_age_seconds is unset, call the API directly
|
359
|
+
# If max_token_age_seconds is set and the JWT was issued (based on the "iat" claim) less than
|
360
|
+
# max_token_age_seconds seconds ago, then just verify locally and don't call the API
|
361
|
+
# To force remote validation for all tokens, set max_token_age_seconds to 0 or call authenticate()
|
362
|
+
# Note that the 'user_id' field of the returned session is DEPRECATED: Use member_id instead
|
363
|
+
# This field will be removed in a future MAJOR release.
|
364
|
+
# If max_token_age_seconds is not supplied 300 seconds will be used as the default.
|
365
|
+
def authenticate_jwt(
|
366
|
+
session_jwt,
|
367
|
+
max_token_age_seconds: nil,
|
368
|
+
session_duration_minutes: nil,
|
369
|
+
session_custom_claims: nil,
|
370
|
+
authorization_check: nil
|
371
|
+
)
|
372
|
+
max_token_age_seconds = 300 if max_token_age_seconds.nil?
|
373
|
+
|
374
|
+
if max_token_age_seconds == 0
|
375
|
+
return authenticate(
|
376
|
+
session_jwt: session_jwt,
|
377
|
+
session_duration_minutes: session_duration_minutes,
|
378
|
+
session_custom_claims: session_custom_claims,
|
379
|
+
authorization_check: authorization_check
|
380
|
+
)
|
381
|
+
end
|
382
|
+
|
383
|
+
decoded_jwt = authenticate_jwt_local(session_jwt, max_token_age_seconds: max_token_age_seconds, authorization_check: authorization_check)
|
384
|
+
return decoded_jwt unless decoded_jwt.nil?
|
385
|
+
|
386
|
+
authenticate(
|
387
|
+
session_jwt: session_jwt,
|
388
|
+
session_duration_minutes: session_duration_minutes,
|
389
|
+
session_custom_claims: session_custom_claims,
|
390
|
+
authorization_check: authorization_check
|
391
|
+
)
|
392
|
+
rescue StandardError
|
393
|
+
# JWT could not be verified locally. Check with the Stytch API.
|
394
|
+
authenticate(
|
395
|
+
session_jwt: session_jwt,
|
396
|
+
session_duration_minutes: session_duration_minutes,
|
397
|
+
session_custom_claims: session_custom_claims,
|
398
|
+
authorization_check: authorization_check
|
399
|
+
)
|
400
|
+
end
|
401
|
+
|
402
|
+
# Parse a JWT and verify the signature locally (without calling /authenticate in the API)
|
403
|
+
# Uses the cached value to get the JWK but if it is unavailable, it calls the get_jwks()
|
404
|
+
# function to get the JWK
|
405
|
+
# This method never authenticates a JWT directly with the API
|
406
|
+
# If max_token_age_seconds is not supplied 300 seconds will be used as the default.
|
407
|
+
def authenticate_jwt_local(session_jwt, max_token_age_seconds: nil, authorization_check: nil)
|
408
|
+
max_token_age_seconds = 300 if max_token_age_seconds.nil?
|
409
|
+
|
410
|
+
issuer = 'stytch.com/' + @project_id
|
411
|
+
begin
|
412
|
+
decoded_token = JWT.decode session_jwt, nil, true,
|
413
|
+
{ jwks: @jwks_loader, iss: issuer, verify_iss: true, aud: @project_id, verify_aud: true, algorithms: ['RS256'] }
|
414
|
+
|
415
|
+
session = decoded_token[0]
|
416
|
+
iat_time = Time.at(session['iat']).to_datetime
|
417
|
+
return nil unless iat_time + max_token_age_seconds >= Time.now
|
418
|
+
|
419
|
+
session = marshal_jwt_into_session(session)
|
420
|
+
rescue JWT::InvalidIssuerError
|
421
|
+
raise Stytch::JWTInvalidIssuerError
|
422
|
+
rescue JWT::InvalidAudError
|
423
|
+
raise Stytch::JWTInvalidAudienceError
|
424
|
+
rescue JWT::ExpiredSignature
|
425
|
+
raise Stytch::JWTExpiredSignatureError
|
426
|
+
rescue JWT::IncorrectAlgorithm
|
427
|
+
raise Stytch::JWTIncorrectAlgorithmError
|
428
|
+
end
|
429
|
+
|
430
|
+
# Do the auth check - intentionally don't rescue errors from here
|
431
|
+
if authorization_check && session['roles']
|
432
|
+
@policy_cache.perform_authorization_check(
|
433
|
+
subject_roles: session['roles'],
|
434
|
+
subject_org_id: session['member_session']['organization_id'],
|
435
|
+
authorization_check: authorization_check
|
436
|
+
)
|
437
|
+
end
|
438
|
+
|
439
|
+
session
|
440
|
+
end
|
441
|
+
|
442
|
+
# Note that the 'user_id' field is DEPRECATED: Use member_id instead
|
443
|
+
# This field will be removed in a future MAJOR release.
|
444
|
+
def marshal_jwt_into_session(jwt)
|
445
|
+
stytch_claim = 'https://stytch.com/session'
|
446
|
+
organization_claim = 'https://stytch.com/organization'
|
447
|
+
|
448
|
+
expires_at = jwt[stytch_claim]['expires_at'] || Time.at(jwt['exp']).to_datetime.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
|
449
|
+
# The custom claim set is all the claims in the payload except for the standard claims and
|
450
|
+
# the Stytch session claim. The cleanest way to collect those seems to be naming what we want
|
451
|
+
# to omit and filtering the rest to collect the custom claims.
|
452
|
+
reserved_claims = ['aud', 'exp', 'iat', 'iss', 'jti', 'nbf', 'sub', stytch_claim, organization_claim]
|
453
|
+
custom_claims = jwt.reject { |key, _| reserved_claims.include?(key) }
|
454
|
+
{
|
455
|
+
'member_session' => {
|
456
|
+
'session_id' => jwt[stytch_claim]['id'],
|
457
|
+
'organization_id' => jwt[organization_claim]['organization_id'],
|
458
|
+
'member_id' => jwt['sub'],
|
459
|
+
# DEPRECATED: Use member_id instead
|
460
|
+
'user_id' => jwt['sub'],
|
461
|
+
'started_at' => jwt[stytch_claim]['started_at'],
|
462
|
+
'last_accessed_at' => jwt[stytch_claim]['last_accessed_at'],
|
463
|
+
# For JWTs that include it, prefer the inner expires_at claim.
|
464
|
+
'expires_at' => expires_at,
|
465
|
+
'attributes' => jwt[stytch_claim]['attributes'],
|
466
|
+
'authentication_factors' => jwt[stytch_claim]['authentication_factors'],
|
467
|
+
'custom_claims' => custom_claims
|
468
|
+
},
|
469
|
+
'roles' => jwt[stytch_claim]['roles']
|
470
|
+
}
|
292
471
|
end
|
472
|
+
# ENDMANUAL(Sessions::authenticate_jwt)
|
293
473
|
end
|
294
474
|
end
|
data/lib/stytch/b2b_sso.rb
CHANGED
@@ -9,6 +9,44 @@
|
|
9
9
|
require_relative 'request_helper'
|
10
10
|
|
11
11
|
module StytchB2B
|
12
|
+
class GetConnectionsRequestOptions
|
13
|
+
# Optional authorization object.
|
14
|
+
# Pass in an active Stytch Member session token or session JWT and the request
|
15
|
+
# will be run using that member's permissions.
|
16
|
+
attr_accessor :authorization
|
17
|
+
|
18
|
+
def initialize(
|
19
|
+
authorization: nil
|
20
|
+
)
|
21
|
+
@authorization = authorization
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_headers
|
25
|
+
headers = {}
|
26
|
+
headers.merge!(@authorization.to_headers) if authorization
|
27
|
+
headers
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class DeleteConnectionRequestOptions
|
32
|
+
# Optional authorization object.
|
33
|
+
# Pass in an active Stytch Member session token or session JWT and the request
|
34
|
+
# will be run using that member's permissions.
|
35
|
+
attr_accessor :authorization
|
36
|
+
|
37
|
+
def initialize(
|
38
|
+
authorization: nil
|
39
|
+
)
|
40
|
+
@authorization = authorization
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_headers
|
44
|
+
headers = {}
|
45
|
+
headers.merge!(@authorization.to_headers) if authorization
|
46
|
+
headers
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
12
50
|
class SSO
|
13
51
|
include Stytch::RequestHelper
|
14
52
|
attr_reader :oidc, :saml
|
@@ -20,7 +58,7 @@ module StytchB2B
|
|
20
58
|
@saml = StytchB2B::SSO::SAML.new(@connection)
|
21
59
|
end
|
22
60
|
|
23
|
-
# Get all SSO Connections owned by the organization.
|
61
|
+
# Get all SSO Connections owned by the organization. /%}
|
24
62
|
#
|
25
63
|
# == Parameters:
|
26
64
|
# organization_id::
|
@@ -41,15 +79,21 @@ module StytchB2B
|
|
41
79
|
# status_code::
|
42
80
|
# 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.
|
43
81
|
# The type of this field is +Integer+.
|
82
|
+
#
|
83
|
+
# == Method Options:
|
84
|
+
# This method supports an optional +GetConnectionsRequestOptions+ object which will modify the headers sent in the HTTP request.
|
44
85
|
def get_connections(
|
45
|
-
organization_id
|
86
|
+
organization_id:,
|
87
|
+
method_options: nil
|
46
88
|
)
|
89
|
+
headers = {}
|
90
|
+
headers = headers.merge(method_options.to_headers) unless method_options.nil?
|
47
91
|
query_params = {}
|
48
92
|
request = request_with_query_params("/v1/b2b/sso/#{organization_id}", query_params)
|
49
|
-
get_request(request)
|
93
|
+
get_request(request, headers)
|
50
94
|
end
|
51
95
|
|
52
|
-
# Delete an existing SSO connection.
|
96
|
+
# Delete an existing SSO connection. /%}
|
53
97
|
#
|
54
98
|
# == Parameters:
|
55
99
|
# organization_id::
|
@@ -70,11 +114,17 @@ module StytchB2B
|
|
70
114
|
# status_code::
|
71
115
|
# 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.
|
72
116
|
# The type of this field is +Integer+.
|
117
|
+
#
|
118
|
+
# == Method Options:
|
119
|
+
# This method supports an optional +DeleteConnectionRequestOptions+ object which will modify the headers sent in the HTTP request.
|
73
120
|
def delete_connection(
|
74
121
|
organization_id:,
|
75
|
-
connection_id
|
122
|
+
connection_id:,
|
123
|
+
method_options: nil
|
76
124
|
)
|
77
|
-
|
125
|
+
headers = {}
|
126
|
+
headers = headers.merge(method_options.to_headers) unless method_options.nil?
|
127
|
+
delete_request("/v1/b2b/sso/#{organization_id}/connections/#{connection_id}", headers)
|
78
128
|
end
|
79
129
|
|
80
130
|
# Authenticate a user given a token.
|
@@ -184,6 +234,7 @@ module StytchB2B
|
|
184
234
|
session_custom_claims: nil,
|
185
235
|
locale: nil
|
186
236
|
)
|
237
|
+
headers = {}
|
187
238
|
request = {
|
188
239
|
sso_token: sso_token
|
189
240
|
}
|
@@ -194,7 +245,7 @@ module StytchB2B
|
|
194
245
|
request[:session_custom_claims] = session_custom_claims unless session_custom_claims.nil?
|
195
246
|
request[:locale] = locale unless locale.nil?
|
196
247
|
|
197
|
-
post_request('/v1/b2b/sso/authenticate', request)
|
248
|
+
post_request('/v1/b2b/sso/authenticate', request, headers)
|
198
249
|
end
|
199
250
|
|
200
251
|
class OIDC
|
@@ -204,7 +255,7 @@ module StytchB2B
|
|
204
255
|
@connection = connection
|
205
256
|
end
|
206
257
|
|
207
|
-
# Create a new OIDC Connection.
|
258
|
+
# Create a new OIDC Connection. /%}
|
208
259
|
#
|
209
260
|
# == Parameters:
|
210
261
|
# organization_id::
|
@@ -225,14 +276,20 @@ module StytchB2B
|
|
225
276
|
# connection::
|
226
277
|
# The `OIDC Connection` object affected by this API call. See the [OIDC Connection Object](https://stytch.com/docs/b2b/api/oidc-connection-object) for complete response field details.
|
227
278
|
# The type of this field is nilable +OIDCConnection+ (+object+).
|
279
|
+
#
|
280
|
+
# == Method Options:
|
281
|
+
# This method supports an optional +CreateConnectionRequestOptions+ object which will modify the headers sent in the HTTP request.
|
228
282
|
def create_connection(
|
229
283
|
organization_id:,
|
230
|
-
display_name: nil
|
284
|
+
display_name: nil,
|
285
|
+
method_options: nil
|
231
286
|
)
|
287
|
+
headers = {}
|
288
|
+
headers = headers.merge(method_options.to_headers) unless method_options.nil?
|
232
289
|
request = {}
|
233
290
|
request[:display_name] = display_name unless display_name.nil?
|
234
291
|
|
235
|
-
post_request("/v1/b2b/sso/oidc/#{organization_id}", request)
|
292
|
+
post_request("/v1/b2b/sso/oidc/#{organization_id}", request, headers)
|
236
293
|
end
|
237
294
|
|
238
295
|
# Updates an existing OIDC connection.
|
@@ -253,6 +310,7 @@ module StytchB2B
|
|
253
310
|
# * `token_url`
|
254
311
|
# * `userinfo_url`
|
255
312
|
# * `jwks_url`
|
313
|
+
# /%}
|
256
314
|
#
|
257
315
|
# == Parameters:
|
258
316
|
# organization_id::
|
@@ -300,6 +358,9 @@ module StytchB2B
|
|
300
358
|
# warning::
|
301
359
|
# If it is not possible to resolve the well-known metadata document from the OIDC issuer, this field will explain what went wrong if the request is successful otherwise. In other words, even if the overall request succeeds, there could be relevant warnings related to the connection update.
|
302
360
|
# The type of this field is nilable +String+.
|
361
|
+
#
|
362
|
+
# == Method Options:
|
363
|
+
# This method supports an optional +UpdateConnectionRequestOptions+ object which will modify the headers sent in the HTTP request.
|
303
364
|
def update_connection(
|
304
365
|
organization_id:,
|
305
366
|
connection_id:,
|
@@ -310,8 +371,11 @@ module StytchB2B
|
|
310
371
|
authorization_url: nil,
|
311
372
|
token_url: nil,
|
312
373
|
userinfo_url: nil,
|
313
|
-
jwks_url: nil
|
374
|
+
jwks_url: nil,
|
375
|
+
method_options: nil
|
314
376
|
)
|
377
|
+
headers = {}
|
378
|
+
headers = headers.merge(method_options.to_headers) unless method_options.nil?
|
315
379
|
request = {}
|
316
380
|
request[:display_name] = display_name unless display_name.nil?
|
317
381
|
request[:client_id] = client_id unless client_id.nil?
|
@@ -322,7 +386,7 @@ module StytchB2B
|
|
322
386
|
request[:userinfo_url] = userinfo_url unless userinfo_url.nil?
|
323
387
|
request[:jwks_url] = jwks_url unless jwks_url.nil?
|
324
388
|
|
325
|
-
put_request("/v1/b2b/sso/oidc/#{organization_id}/connections/#{connection_id}", request)
|
389
|
+
put_request("/v1/b2b/sso/oidc/#{organization_id}/connections/#{connection_id}", request, headers)
|
326
390
|
end
|
327
391
|
end
|
328
392
|
|
@@ -333,7 +397,7 @@ module StytchB2B
|
|
333
397
|
@connection = connection
|
334
398
|
end
|
335
399
|
|
336
|
-
# Create a new SAML Connection.
|
400
|
+
# Create a new SAML Connection. /%}
|
337
401
|
#
|
338
402
|
# == Parameters:
|
339
403
|
# organization_id::
|
@@ -354,14 +418,20 @@ module StytchB2B
|
|
354
418
|
# connection::
|
355
419
|
# The `SAML Connection` object affected by this API call. See the [SAML Connection Object](https://stytch.com/docs/b2b/api/saml-connection-object) for complete response field details.
|
356
420
|
# The type of this field is nilable +SAMLConnection+ (+object+).
|
421
|
+
#
|
422
|
+
# == Method Options:
|
423
|
+
# This method supports an optional +CreateConnectionRequestOptions+ object which will modify the headers sent in the HTTP request.
|
357
424
|
def create_connection(
|
358
425
|
organization_id:,
|
359
|
-
display_name: nil
|
426
|
+
display_name: nil,
|
427
|
+
method_options: nil
|
360
428
|
)
|
429
|
+
headers = {}
|
430
|
+
headers = headers.merge(method_options.to_headers) unless method_options.nil?
|
361
431
|
request = {}
|
362
432
|
request[:display_name] = display_name unless display_name.nil?
|
363
433
|
|
364
|
-
post_request("/v1/b2b/sso/saml/#{organization_id}", request)
|
434
|
+
post_request("/v1/b2b/sso/saml/#{organization_id}", request, headers)
|
365
435
|
end
|
366
436
|
|
367
437
|
# Updates an existing SAML connection.
|
@@ -371,6 +441,7 @@ module StytchB2B
|
|
371
441
|
# * `attribute_mapping`
|
372
442
|
# * `idp_entity_id`
|
373
443
|
# * `x509_certificate`
|
444
|
+
# /%}
|
374
445
|
#
|
375
446
|
# == Parameters:
|
376
447
|
# organization_id::
|
@@ -394,6 +465,20 @@ module StytchB2B
|
|
394
465
|
# idp_sso_url::
|
395
466
|
# The URL for which assertions for login requests will be sent. This will be provided by the IdP.
|
396
467
|
# The type of this field is nilable +String+.
|
468
|
+
# saml_connection_implicit_role_assignments::
|
469
|
+
# All Members who log in with this SAML connection will implicitly receive the specified Roles. See the [RBAC guide](https://stytch.com/docs/b2b/guides/rbac/role-assignment) for more information about role assignment.
|
470
|
+
# The type of this field is nilable list of +String+.
|
471
|
+
# saml_group_implicit_role_assignments::
|
472
|
+
# Defines the names of the SAML groups
|
473
|
+
# that grant specific role assignments. For each group-Role pair, if a Member logs in with this SAML connection and
|
474
|
+
# belongs to the specified SAML group, they will be granted the associated Role. See the
|
475
|
+
# [RBAC guide](https://stytch.com/docs/b2b/guides/rbac/role-assignment) for more information about role assignment.
|
476
|
+
# Before adding any group implicit role assignments, you must add a "groups" key to your SAML connection's
|
477
|
+
# `attribute_mapping`. Make sure that your IdP is configured to correctly send the group information.
|
478
|
+
# The type of this field is nilable list of +String+.
|
479
|
+
# alternative_audience_uri::
|
480
|
+
# An alternative URL to use for the Audience Restriction. This value can be used when you wish to migrate an existing SAML integration to Stytch with zero downtime.
|
481
|
+
# The type of this field is nilable +String+.
|
397
482
|
#
|
398
483
|
# == Returns:
|
399
484
|
# An object with the following fields:
|
@@ -406,6 +491,9 @@ module StytchB2B
|
|
406
491
|
# connection::
|
407
492
|
# The `SAML Connection` object affected by this API call. See the [SAML Connection Object](https://stytch.com/docs/b2b/api/saml-connection-object) for complete response field details.
|
408
493
|
# The type of this field is nilable +SAMLConnection+ (+object+).
|
494
|
+
#
|
495
|
+
# == Method Options:
|
496
|
+
# This method supports an optional +UpdateConnectionRequestOptions+ object which will modify the headers sent in the HTTP request.
|
409
497
|
def update_connection(
|
410
498
|
organization_id:,
|
411
499
|
connection_id:,
|
@@ -413,21 +501,80 @@ module StytchB2B
|
|
413
501
|
display_name: nil,
|
414
502
|
attribute_mapping: nil,
|
415
503
|
x509_certificate: nil,
|
416
|
-
idp_sso_url: nil
|
504
|
+
idp_sso_url: nil,
|
505
|
+
saml_connection_implicit_role_assignments: nil,
|
506
|
+
saml_group_implicit_role_assignments: nil,
|
507
|
+
alternative_audience_uri: nil,
|
508
|
+
method_options: nil
|
417
509
|
)
|
510
|
+
headers = {}
|
511
|
+
headers = headers.merge(method_options.to_headers) unless method_options.nil?
|
418
512
|
request = {}
|
419
513
|
request[:idp_entity_id] = idp_entity_id unless idp_entity_id.nil?
|
420
514
|
request[:display_name] = display_name unless display_name.nil?
|
421
515
|
request[:attribute_mapping] = attribute_mapping unless attribute_mapping.nil?
|
422
516
|
request[:x509_certificate] = x509_certificate unless x509_certificate.nil?
|
423
517
|
request[:idp_sso_url] = idp_sso_url unless idp_sso_url.nil?
|
518
|
+
request[:saml_connection_implicit_role_assignments] = saml_connection_implicit_role_assignments unless saml_connection_implicit_role_assignments.nil?
|
519
|
+
request[:saml_group_implicit_role_assignments] = saml_group_implicit_role_assignments unless saml_group_implicit_role_assignments.nil?
|
520
|
+
request[:alternative_audience_uri] = alternative_audience_uri unless alternative_audience_uri.nil?
|
424
521
|
|
425
|
-
put_request("/v1/b2b/sso/saml/#{organization_id}/connections/#{connection_id}", request)
|
522
|
+
put_request("/v1/b2b/sso/saml/#{organization_id}/connections/#{connection_id}", request, headers)
|
523
|
+
end
|
524
|
+
|
525
|
+
# Used to update an existing SAML connection using an IDP metadata URL.
|
526
|
+
#
|
527
|
+
# A newly created connection will not become active until all the following are provided:
|
528
|
+
# * `idp_sso_url`
|
529
|
+
# * `idp_entity_id`
|
530
|
+
# * `x509_certificate`
|
531
|
+
# * `attribute_mapping` (must be supplied using [Update SAML Connection](update-saml-connection))
|
532
|
+
# /%}
|
533
|
+
#
|
534
|
+
# == Parameters:
|
535
|
+
# organization_id::
|
536
|
+
# 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.
|
537
|
+
# The type of this field is +String+.
|
538
|
+
# connection_id::
|
539
|
+
# Globally unique UUID that identifies a specific SSO `connection_id` for a Member.
|
540
|
+
# The type of this field is +String+.
|
541
|
+
# metadata_url::
|
542
|
+
# A URL that points to the IdP metadata. This will be provided by the IdP.
|
543
|
+
# The type of this field is +String+.
|
544
|
+
#
|
545
|
+
# == Returns:
|
546
|
+
# An object with the following fields:
|
547
|
+
# request_id::
|
548
|
+
# 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.
|
549
|
+
# The type of this field is +String+.
|
550
|
+
# status_code::
|
551
|
+
# 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.
|
552
|
+
# The type of this field is +Integer+.
|
553
|
+
# connection::
|
554
|
+
# The `SAML Connection` object affected by this API call. See the [SAML Connection Object](https://stytch.com/docs/b2b/api/saml-connection-object) for complete response field details.
|
555
|
+
# The type of this field is nilable +SAMLConnection+ (+object+).
|
556
|
+
#
|
557
|
+
# == Method Options:
|
558
|
+
# This method supports an optional +UpdateByURLRequestOptions+ object which will modify the headers sent in the HTTP request.
|
559
|
+
def update_by_url(
|
560
|
+
organization_id:,
|
561
|
+
connection_id:,
|
562
|
+
metadata_url:,
|
563
|
+
method_options: nil
|
564
|
+
)
|
565
|
+
headers = {}
|
566
|
+
headers = headers.merge(method_options.to_headers) unless method_options.nil?
|
567
|
+
request = {
|
568
|
+
metadata_url: metadata_url
|
569
|
+
}
|
570
|
+
|
571
|
+
put_request("/v1/b2b/sso/saml/#{organization_id}/connections/#{connection_id}/url", request, headers)
|
426
572
|
end
|
427
573
|
|
428
574
|
# Delete a SAML verification certificate.
|
429
575
|
#
|
430
576
|
# You may need to do this when rotating certificates from your IdP, since Stytch allows a maximum of 5 certificates per connection. There must always be at least one certificate per active connection.
|
577
|
+
# /%}
|
431
578
|
#
|
432
579
|
# == Parameters:
|
433
580
|
# organization_id::
|
@@ -451,12 +598,18 @@ module StytchB2B
|
|
451
598
|
# status_code::
|
452
599
|
# 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.
|
453
600
|
# The type of this field is +Integer+.
|
601
|
+
#
|
602
|
+
# == Method Options:
|
603
|
+
# This method supports an optional +DeleteVerificationCertificateRequestOptions+ object which will modify the headers sent in the HTTP request.
|
454
604
|
def delete_verification_certificate(
|
455
605
|
organization_id:,
|
456
606
|
connection_id:,
|
457
|
-
certificate_id
|
607
|
+
certificate_id:,
|
608
|
+
method_options: nil
|
458
609
|
)
|
459
|
-
|
610
|
+
headers = {}
|
611
|
+
headers = headers.merge(method_options.to_headers) unless method_options.nil?
|
612
|
+
delete_request("/v1/b2b/sso/saml/#{organization_id}/connections/#{connection_id}/verification_certificates/#{certificate_id}", headers)
|
460
613
|
end
|
461
614
|
end
|
462
615
|
end
|