stytch 10.35.0 → 10.37.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 +9 -5
- data/lib/stytch/b2b_idp.rb +3 -14
- data/lib/stytch/b2b_sessions.rb +3 -14
- data/lib/stytch/client.rb +9 -5
- data/lib/stytch/idp.rb +3 -14
- data/lib/stytch/jwks_cache.rb +52 -0
- data/lib/stytch/m2m.rb +3 -14
- data/lib/stytch/middleware.rb +5 -1
- data/lib/stytch/sessions.rb +3 -14
- data/lib/stytch/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2636f56ed7d78577fb1ff81133a92fc1c0fb2500696f7921dcff85d6e79d7995
|
4
|
+
data.tar.gz: 932c0aa9dcef45bfb75a82516508bceac612f89a4b4a55e1555103017f80ba55
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 988ed498a5b30318230b13dd477125149ce76ca35bedab317843ce4b77f9ed0857d375f165e0268eb5d0877ae9ddda12f2fca221f2d82d95d14bb7dcf9f7e8e8
|
7
|
+
data.tar.gz: fa274f938a19f3f8241288467d7724e1a63a5c43695fdce8ea7626ce38e005ce76b71a7af799028356660728f8510abfb41d46ec31d3f999049adeea9354b852
|
data/lib/stytch/b2b_client.rb
CHANGED
@@ -23,6 +23,7 @@ require_relative 'b2b_totps'
|
|
23
23
|
require_relative 'connected_apps'
|
24
24
|
require_relative 'debug'
|
25
25
|
require_relative 'fraud'
|
26
|
+
require_relative 'jwks_cache'
|
26
27
|
require_relative 'm2m'
|
27
28
|
require_relative 'project'
|
28
29
|
require_relative 'rbac_local'
|
@@ -33,15 +34,18 @@ module StytchB2B
|
|
33
34
|
|
34
35
|
attr_reader :connected_app, :debug, :discovery, :fraud, :idp, :impersonation, :m2m, :magic_links, :oauth, :otps, :organizations, :passwords, :project, :rbac, :recovery_codes, :scim, :sso, :sessions, :totps
|
35
36
|
|
36
|
-
def initialize(project_id:, secret:, env: nil, fraud_env: nil, &block)
|
37
|
+
def initialize(project_id:, secret:, env: nil, fraud_env: nil, timeout: nil, jwks: nil, &block)
|
37
38
|
@api_host = api_host(env, project_id)
|
38
39
|
@fraud_api_host = fraud_api_host(fraud_env)
|
39
40
|
@project_id = project_id
|
40
41
|
@secret = secret
|
42
|
+
@timeout = timeout
|
41
43
|
@is_b2b_client = true
|
42
44
|
|
43
45
|
create_connection(&block)
|
44
46
|
|
47
|
+
@jwks_cache = Stytch::JWKSCache.new(@connection, @project_id, jwks)
|
48
|
+
|
45
49
|
rbac = StytchB2B::RBAC.new(@connection)
|
46
50
|
@policy_cache = Stytch::PolicyCache.new(rbac_client: rbac)
|
47
51
|
|
@@ -49,9 +53,9 @@ module StytchB2B
|
|
49
53
|
@debug = Stytch::Debug.new(@connection)
|
50
54
|
@discovery = StytchB2B::Discovery.new(@connection)
|
51
55
|
@fraud = Stytch::Fraud.new(@fraud_connection)
|
52
|
-
@idp = StytchB2B::IDP.new(@connection, @project_id, @policy_cache)
|
56
|
+
@idp = StytchB2B::IDP.new(@connection, @project_id, @jwks_cache, @policy_cache)
|
53
57
|
@impersonation = StytchB2B::Impersonation.new(@connection)
|
54
|
-
@m2m = Stytch::M2M.new(@connection, @project_id, @is_b2b_client)
|
58
|
+
@m2m = Stytch::M2M.new(@connection, @project_id, @is_b2b_client, @jwks_cache)
|
55
59
|
@magic_links = StytchB2B::MagicLinks.new(@connection)
|
56
60
|
@oauth = StytchB2B::OAuth.new(@connection)
|
57
61
|
@otps = StytchB2B::OTPs.new(@connection)
|
@@ -62,7 +66,7 @@ module StytchB2B
|
|
62
66
|
@recovery_codes = StytchB2B::RecoveryCodes.new(@connection)
|
63
67
|
@scim = StytchB2B::SCIM.new(@connection)
|
64
68
|
@sso = StytchB2B::SSO.new(@connection)
|
65
|
-
@sessions = StytchB2B::Sessions.new(@connection, @project_id, @policy_cache)
|
69
|
+
@sessions = StytchB2B::Sessions.new(@connection, @project_id, @jwks_cache, @policy_cache)
|
66
70
|
@totps = StytchB2B::TOTPs.new(@connection)
|
67
71
|
end
|
68
72
|
|
@@ -108,7 +112,7 @@ module StytchB2B
|
|
108
112
|
end
|
109
113
|
|
110
114
|
def build_default_connection(builder)
|
111
|
-
builder.options[:timeout] = Stytch::Middleware
|
115
|
+
builder.options[:timeout] = Stytch::Middleware.timeout(@timeout)
|
112
116
|
builder.headers = Stytch::Middleware::NETWORK_HEADERS
|
113
117
|
builder.request :json
|
114
118
|
builder.use Stytch::Middleware
|
data/lib/stytch/b2b_idp.rb
CHANGED
@@ -16,24 +16,13 @@ module StytchB2B
|
|
16
16
|
include Stytch::RequestHelper
|
17
17
|
attr_reader :oauth
|
18
18
|
|
19
|
-
def initialize(connection, project_id, policy_cache)
|
19
|
+
def initialize(connection, project_id, jwks_cache, policy_cache)
|
20
20
|
@connection = connection
|
21
21
|
|
22
22
|
@oauth = StytchB2B::IDP::OAuth.new(@connection)
|
23
23
|
@policy_cache = policy_cache
|
24
24
|
@project_id = project_id
|
25
|
-
@
|
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
|
25
|
+
@jwks_cache = jwks_cache
|
37
26
|
end
|
38
27
|
|
39
28
|
# MANUAL(IDP::introspect_token_network)(SERVICE_METHOD)
|
@@ -199,7 +188,7 @@ module StytchB2B
|
|
199
188
|
true,
|
200
189
|
{
|
201
190
|
algorithms: ['RS256'],
|
202
|
-
jwks: @
|
191
|
+
jwks: @jwks_cache.loader,
|
203
192
|
iss: ["stytch.com/#{@project_id}", @connection.url_prefix],
|
204
193
|
aud: @project_id
|
205
194
|
}
|
data/lib/stytch/b2b_sessions.rb
CHANGED
@@ -34,23 +34,12 @@ module StytchB2B
|
|
34
34
|
|
35
35
|
include Stytch::RequestHelper
|
36
36
|
|
37
|
-
def initialize(connection, project_id, policy_cache)
|
37
|
+
def initialize(connection, project_id, jwks_cache, policy_cache)
|
38
38
|
@connection = connection
|
39
39
|
|
40
40
|
@policy_cache = policy_cache
|
41
41
|
@project_id = project_id
|
42
|
-
@
|
43
|
-
@jwks_loader = lambda do |options|
|
44
|
-
@cached_keys = nil if options[:invalidate] && @cache_last_update < Time.now.to_i - 300
|
45
|
-
@cached_keys ||= begin
|
46
|
-
@cache_last_update = Time.now.to_i
|
47
|
-
keys = []
|
48
|
-
get_jwks(project_id: @project_id)['keys'].each do |r|
|
49
|
-
keys << r
|
50
|
-
end
|
51
|
-
{ keys: keys }
|
52
|
-
end
|
53
|
-
end
|
42
|
+
@jwks_cache = jwks_cache
|
54
43
|
end
|
55
44
|
|
56
45
|
# Retrieves all active Sessions for a Member.
|
@@ -706,7 +695,7 @@ module StytchB2B
|
|
706
695
|
|
707
696
|
begin
|
708
697
|
decoded_token = JWT.decode session_jwt, nil, true,
|
709
|
-
{ jwks: @
|
698
|
+
{ jwks: @jwks_cache.loader, iss: valid_issuers, verify_iss: true, aud: @project_id, verify_aud: true, algorithms: ['RS256'], nbf_leeway: clock_tolerance_seconds }
|
710
699
|
|
711
700
|
session = decoded_token[0]
|
712
701
|
iat_time = Time.at(session['iat']).to_datetime
|
data/lib/stytch/client.rb
CHANGED
@@ -12,6 +12,7 @@ require_relative 'debug'
|
|
12
12
|
require_relative 'fraud'
|
13
13
|
require_relative 'idp'
|
14
14
|
require_relative 'impersonation'
|
15
|
+
require_relative 'jwks_cache'
|
15
16
|
require_relative 'm2m'
|
16
17
|
require_relative 'magic_links'
|
17
18
|
require_relative 'oauth'
|
@@ -31,15 +32,18 @@ module Stytch
|
|
31
32
|
|
32
33
|
attr_reader :connected_app, :crypto_wallets, :debug, :fraud, :idp, :impersonation, :m2m, :magic_links, :oauth, :otps, :passwords, :project, :rbac, :sessions, :totps, :users, :webauthn
|
33
34
|
|
34
|
-
def initialize(project_id:, secret:, env: nil, fraud_env: nil, &block)
|
35
|
+
def initialize(project_id:, secret:, env: nil, fraud_env: nil, timeout: nil, jwks: nil, &block)
|
35
36
|
@api_host = api_host(env, project_id)
|
36
37
|
@fraud_api_host = fraud_api_host(fraud_env)
|
37
38
|
@project_id = project_id
|
38
39
|
@secret = secret
|
40
|
+
@timeout = timeout
|
39
41
|
@is_b2b_client = false
|
40
42
|
|
41
43
|
create_connection(&block)
|
42
44
|
|
45
|
+
@jwks_cache = Stytch::JWKSCache.new(@connection, @project_id, jwks)
|
46
|
+
|
43
47
|
rbac = Stytch::RBAC.new(@connection)
|
44
48
|
@policy_cache = Stytch::PolicyCache.new(rbac_client: rbac)
|
45
49
|
|
@@ -47,16 +51,16 @@ module Stytch
|
|
47
51
|
@crypto_wallets = Stytch::CryptoWallets.new(@connection)
|
48
52
|
@debug = Stytch::Debug.new(@connection)
|
49
53
|
@fraud = Stytch::Fraud.new(@fraud_connection)
|
50
|
-
@idp = Stytch::IDP.new(@connection, @project_id, @policy_cache)
|
54
|
+
@idp = Stytch::IDP.new(@connection, @project_id, @jwks_cache, @policy_cache)
|
51
55
|
@impersonation = Stytch::Impersonation.new(@connection)
|
52
|
-
@m2m = Stytch::M2M.new(@connection, @project_id, @is_b2b_client)
|
56
|
+
@m2m = Stytch::M2M.new(@connection, @project_id, @is_b2b_client, @jwks_cache)
|
53
57
|
@magic_links = Stytch::MagicLinks.new(@connection)
|
54
58
|
@oauth = Stytch::OAuth.new(@connection)
|
55
59
|
@otps = Stytch::OTPs.new(@connection)
|
56
60
|
@passwords = Stytch::Passwords.new(@connection)
|
57
61
|
@project = Stytch::Project.new(@connection)
|
58
62
|
@rbac = Stytch::RBAC.new(@connection)
|
59
|
-
@sessions = Stytch::Sessions.new(@connection, @project_id, @policy_cache)
|
63
|
+
@sessions = Stytch::Sessions.new(@connection, @project_id, @jwks_cache, @policy_cache)
|
60
64
|
@totps = Stytch::TOTPs.new(@connection)
|
61
65
|
@users = Stytch::Users.new(@connection)
|
62
66
|
@webauthn = Stytch::WebAuthn.new(@connection)
|
@@ -104,7 +108,7 @@ module Stytch
|
|
104
108
|
end
|
105
109
|
|
106
110
|
def build_default_connection(builder)
|
107
|
-
builder.options[:timeout] = Stytch::Middleware
|
111
|
+
builder.options[:timeout] = Stytch::Middleware.timeout(@timeout)
|
108
112
|
builder.headers = Stytch::Middleware::NETWORK_HEADERS
|
109
113
|
builder.request :json
|
110
114
|
builder.use Stytch::Middleware
|
data/lib/stytch/idp.rb
CHANGED
@@ -16,24 +16,13 @@ module Stytch
|
|
16
16
|
include Stytch::RequestHelper
|
17
17
|
attr_reader :oauth
|
18
18
|
|
19
|
-
def initialize(connection, project_id, policy_cache)
|
19
|
+
def initialize(connection, project_id, jwks_cache, policy_cache)
|
20
20
|
@connection = connection
|
21
21
|
|
22
22
|
@oauth = Stytch::IDP::OAuth.new(@connection)
|
23
23
|
@policy_cache = policy_cache
|
24
24
|
@project_id = project_id
|
25
|
-
@
|
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
|
25
|
+
@jwks_cache = jwks_cache
|
37
26
|
end
|
38
27
|
|
39
28
|
# MANUAL(IDP::introspect_token_network)(SERVICE_METHOD)
|
@@ -188,7 +177,7 @@ module Stytch
|
|
188
177
|
true,
|
189
178
|
{
|
190
179
|
algorithms: ['RS256'],
|
191
|
-
jwks: @
|
180
|
+
jwks: @jwks_cache.loader,
|
192
181
|
iss: ["stytch.com/#{@project_id}", @connection.url_prefix],
|
193
182
|
aud: @project_id
|
194
183
|
}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'request_helper'
|
4
|
+
|
5
|
+
module Stytch
|
6
|
+
# JWKSCache handles caching and refreshing of JSON Web Key Sets (JWKS)
|
7
|
+
# for JWT signature verification. It can be initialized with pre-cached
|
8
|
+
# keys or will fetch them on-demand from the Stytch API.
|
9
|
+
class JWKSCache
|
10
|
+
include Stytch::RequestHelper
|
11
|
+
|
12
|
+
CACHE_EXPIRY_SECONDS = 300 # 5 minutes
|
13
|
+
|
14
|
+
def initialize(connection, project_id, jwks = nil)
|
15
|
+
@connection = connection
|
16
|
+
@project_id = project_id
|
17
|
+
@cache_last_update = 0
|
18
|
+
|
19
|
+
# If jwks are provided during initialization, use them directly
|
20
|
+
return unless jwks
|
21
|
+
|
22
|
+
@cached_keys = { keys: jwks }
|
23
|
+
@cache_last_update = Time.now.to_i
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns a lambda suitable for use with JWT.decode
|
27
|
+
def loader
|
28
|
+
lambda do |options|
|
29
|
+
@cached_keys = nil if options[:invalidate] && @cache_last_update < Time.now.to_i - CACHE_EXPIRY_SECONDS
|
30
|
+
@cached_keys ||= begin
|
31
|
+
@cache_last_update = Time.now.to_i
|
32
|
+
keys = []
|
33
|
+
get_jwks(project_id: @project_id)['keys'].each do |r|
|
34
|
+
keys << r
|
35
|
+
end
|
36
|
+
{ keys: keys }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Fetches JWKS from the Stytch API
|
42
|
+
def get_jwks(project_id:)
|
43
|
+
request_with_query_params(
|
44
|
+
@connection,
|
45
|
+
'/v1/sessions/jwks/%<project_id>s',
|
46
|
+
{
|
47
|
+
project_id: project_id
|
48
|
+
}
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/stytch/m2m.rb
CHANGED
@@ -13,24 +13,13 @@ module Stytch
|
|
13
13
|
include Stytch::RequestHelper
|
14
14
|
attr_reader :clients
|
15
15
|
|
16
|
-
def initialize(connection, project_id, is_b2b_client)
|
16
|
+
def initialize(connection, project_id, is_b2b_client, jwks_cache)
|
17
17
|
@connection = connection
|
18
18
|
|
19
19
|
@clients = Stytch::M2M::Clients.new(@connection)
|
20
20
|
@project_id = project_id
|
21
|
-
@
|
21
|
+
@jwks_cache = jwks_cache
|
22
22
|
@is_b2b_client = is_b2b_client
|
23
|
-
@jwks_loader = lambda do |options|
|
24
|
-
@cached_keys = nil if options[:invalidate] && @cache_last_update < Time.now.to_i - 300
|
25
|
-
@cached_keys ||= begin
|
26
|
-
@cache_last_update = Time.now.to_i
|
27
|
-
keys = []
|
28
|
-
get_jwks(project_id: @project_id)['keys'].each do |r|
|
29
|
-
keys << r
|
30
|
-
end
|
31
|
-
{ keys: keys }
|
32
|
-
end
|
33
|
-
end
|
34
23
|
end
|
35
24
|
|
36
25
|
# MANUAL(M2M::get_jwks)(SERVICE_METHOD)
|
@@ -190,7 +179,7 @@ module Stytch
|
|
190
179
|
|
191
180
|
begin
|
192
181
|
decoded_token = JWT.decode jwt, nil, true,
|
193
|
-
{ jwks: @
|
182
|
+
{ jwks: @jwks_cache.loader, iss: valid_issuers, verify_iss: true, aud: @project_id, verify_aud: true, algorithms: ['RS256'], nbf_leeway: clock_tolerance_seconds }
|
194
183
|
decoded_token[0]
|
195
184
|
rescue JWT::InvalidIssuerError
|
196
185
|
raise JWTInvalidIssuerError
|
data/lib/stytch/middleware.rb
CHANGED
data/lib/stytch/sessions.rb
CHANGED
@@ -15,23 +15,12 @@ module Stytch
|
|
15
15
|
class Sessions
|
16
16
|
include Stytch::RequestHelper
|
17
17
|
|
18
|
-
def initialize(connection, project_id, policy_cache)
|
18
|
+
def initialize(connection, project_id, jwks_cache, policy_cache)
|
19
19
|
@connection = connection
|
20
20
|
|
21
21
|
@policy_cache = policy_cache
|
22
22
|
@project_id = project_id
|
23
|
-
@
|
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
|
23
|
+
@jwks_cache = jwks_cache
|
35
24
|
end
|
36
25
|
|
37
26
|
# List all active Sessions for a given `user_id`. All timestamps are formatted according to the RFC 3339 standard and are expressed in UTC, e.g. `2021-12-29T12:33:09Z`.
|
@@ -514,7 +503,7 @@ module Stytch
|
|
514
503
|
|
515
504
|
begin
|
516
505
|
decoded_token = JWT.decode session_jwt, nil, true,
|
517
|
-
{ jwks: @
|
506
|
+
{ jwks: @jwks_cache.loader, iss: valid_issuers, verify_iss: true, aud: @project_id, verify_aud: true, algorithms: ['RS256'], nbf_leeway: clock_tolerance_seconds }
|
518
507
|
|
519
508
|
session = decoded_token[0]
|
520
509
|
iat_time = Time.at(session['iat']).to_datetime
|
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.37.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-09-
|
11
|
+
date: 2025-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -147,6 +147,7 @@ files:
|
|
147
147
|
- lib/stytch/fraud.rb
|
148
148
|
- lib/stytch/idp.rb
|
149
149
|
- lib/stytch/impersonation.rb
|
150
|
+
- lib/stytch/jwks_cache.rb
|
150
151
|
- lib/stytch/m2m.rb
|
151
152
|
- lib/stytch/magic_links.rb
|
152
153
|
- lib/stytch/method_options.rb
|