stytch 6.4.0 → 6.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/stytch/b2b_client.rb +1 -1
- data/lib/stytch/b2b_sessions.rb +105 -1
- data/lib/stytch/magic_links.rb +1 -3
- data/lib/stytch/otps.rb +3 -9
- data/lib/stytch/users.rb +1 -1
- 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: f0bc5efc1c2c0c36d794db592adba102628de2cd5cec77ffce94652b31e0007f
|
4
|
+
data.tar.gz: 689602f4ab5dc19c149c541eb3b15125d82ce515db9771583b8d6f22123eb577
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be5a989fee14537da3dac34ecea235509a9b1a1366fc1d9539c79ea600ea4b9abb9f9205faee9bfca0ad8ad07429d659d46af6f9b8815ac17343d8757fcc2098
|
7
|
+
data.tar.gz: e4f51e5f088df37798b52df974c376a52ebd3375270278b647b6e8d41e0355b5b1f4af53149cc1459eb5b7ca5b8f617bbe375e4ec57f55eb8819310662b09e9c
|
data/lib/stytch/b2b_client.rb
CHANGED
@@ -31,7 +31,7 @@ module StytchB2B
|
|
31
31
|
@organizations = StytchB2B::Organizations.new(@connection)
|
32
32
|
@passwords = StytchB2B::Passwords.new(@connection)
|
33
33
|
@sso = StytchB2B::SSO.new(@connection)
|
34
|
-
@sessions = StytchB2B::Sessions.new(@connection)
|
34
|
+
@sessions = StytchB2B::Sessions.new(@connection, project_id)
|
35
35
|
end
|
36
36
|
|
37
37
|
private
|
data/lib/stytch/b2b_sessions.rb
CHANGED
@@ -6,14 +6,31 @@
|
|
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)
|
16
19
|
@connection = connection
|
20
|
+
|
21
|
+
@project_id = project_id
|
22
|
+
@cache_last_update = 0
|
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
|
17
34
|
end
|
18
35
|
|
19
36
|
# Retrieves all active Sessions for a Member.
|
@@ -290,5 +307,92 @@ module StytchB2B
|
|
290
307
|
request = request_with_query_params("/v1/b2b/sessions/jwks/#{project_id}", query_params)
|
291
308
|
get_request(request)
|
292
309
|
end
|
310
|
+
|
311
|
+
# MANUAL(Sessions::authenticate_jwt)(SERVICE_METHOD)
|
312
|
+
# ADDIMPORT: require 'jwt'
|
313
|
+
# ADDIMPORT: require 'json/jwt'
|
314
|
+
# ADDIMPORT: require_relative 'errors'
|
315
|
+
|
316
|
+
# Parse a JWT and verify the signature. If max_token_age_seconds is unset, call the API directly
|
317
|
+
# If max_token_age_seconds is set and the JWT was issued (based on the "iat" claim) less than
|
318
|
+
# max_token_age_seconds seconds ago, then just verify locally and don't call the API
|
319
|
+
# To force remote validation for all tokens, set max_token_age_seconds to 0 or call authenticate()
|
320
|
+
def authenticate_jwt(
|
321
|
+
session_jwt,
|
322
|
+
max_token_age_seconds: nil,
|
323
|
+
session_duration_minutes: nil,
|
324
|
+
session_custom_claims: nil
|
325
|
+
)
|
326
|
+
if max_token_age_seconds == 0
|
327
|
+
return authenticate(
|
328
|
+
session_jwt: session_jwt,
|
329
|
+
session_duration_minutes: session_duration_minutes,
|
330
|
+
session_custom_claims: session_custom_claims
|
331
|
+
)
|
332
|
+
end
|
333
|
+
|
334
|
+
decoded_jwt = authenticate_jwt_local(session_jwt)
|
335
|
+
iat_time = Time.at(decoded_jwt['iat']).to_datetime
|
336
|
+
if iat_time + max_token_age_seconds >= Time.now
|
337
|
+
session = marshal_jwt_into_session(decoded_jwt)
|
338
|
+
{ 'session' => session }
|
339
|
+
else
|
340
|
+
authenticate(
|
341
|
+
session_jwt: session_jwt,
|
342
|
+
session_duration_minutes: session_duration_minutes,
|
343
|
+
session_custom_claims: session_custom_claims
|
344
|
+
)
|
345
|
+
end
|
346
|
+
rescue StandardError
|
347
|
+
# JWT could not be verified locally. Check with the Stytch API.
|
348
|
+
authenticate(
|
349
|
+
session_jwt: session_jwt,
|
350
|
+
session_duration_minutes: session_duration_minutes,
|
351
|
+
session_custom_claims: session_custom_claims
|
352
|
+
)
|
353
|
+
end
|
354
|
+
|
355
|
+
# Parse a JWT and verify the signature locally (without calling /authenticate in the API)
|
356
|
+
# Uses the cached value to get the JWK but if it is unavailable, it calls the get_jwks()
|
357
|
+
# function to get the JWK
|
358
|
+
# This method never authenticates a JWT directly with the API
|
359
|
+
def authenticate_jwt_local(session_jwt)
|
360
|
+
issuer = 'stytch.com/' + @project_id
|
361
|
+
begin
|
362
|
+
decoded_token = JWT.decode session_jwt, nil, true,
|
363
|
+
{ jwks: @jwks_loader, iss: issuer, verify_iss: true, aud: @project_id, verify_aud: true, algorithms: ['RS256'] }
|
364
|
+
decoded_token[0]
|
365
|
+
rescue JWT::InvalidIssuerError
|
366
|
+
raise JWTInvalidIssuerError
|
367
|
+
rescue JWT::InvalidAudError
|
368
|
+
raise JWTInvalidAudienceError
|
369
|
+
rescue JWT::ExpiredSignature
|
370
|
+
raise JWTExpiredSignatureError
|
371
|
+
rescue JWT::IncorrectAlgorithm
|
372
|
+
raise JWTIncorrectAlgorithmError
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
def marshal_jwt_into_session(jwt)
|
377
|
+
stytch_claim = 'https://stytch.com/session'
|
378
|
+
expires_at = jwt[stytch_claim]['expires_at'] || Time.at(jwt['exp']).to_datetime.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
|
379
|
+
# The custom claim set is all the claims in the payload except for the standard claims and
|
380
|
+
# the Stytch session claim. The cleanest way to collect those seems to be naming what we want
|
381
|
+
# to omit and filtering the rest to collect the custom claims.
|
382
|
+
reserved_claims = ['aud', 'exp', 'iat', 'iss', 'jti', 'nbf', 'sub', stytch_claim]
|
383
|
+
custom_claims = jwt.reject { |key, _| reserved_claims.include?(key) }
|
384
|
+
{
|
385
|
+
'session_id' => jwt[stytch_claim]['id'],
|
386
|
+
'user_id' => jwt['sub'],
|
387
|
+
'started_at' => jwt[stytch_claim]['started_at'],
|
388
|
+
'last_accessed_at' => jwt[stytch_claim]['last_accessed_at'],
|
389
|
+
# For JWTs that include it, prefer the inner expires_at claim.
|
390
|
+
'expires_at' => expires_at,
|
391
|
+
'attributes' => jwt[stytch_claim]['attributes'],
|
392
|
+
'authentication_factors' => jwt[stytch_claim]['authentication_factors'],
|
393
|
+
'custom_claims' => custom_claims
|
394
|
+
}
|
395
|
+
end
|
396
|
+
# ENDMANUAL(Sessions::authenticate_jwt)
|
293
397
|
end
|
294
398
|
end
|
data/lib/stytch/magic_links.rb
CHANGED
@@ -167,9 +167,7 @@ module Stytch
|
|
167
167
|
# Send a magic link to an existing Stytch user using their email address. If you'd like to create a user and send them a magic link by email with one request, use our [log in or create endpoint](https://stytch.com/docs/api/log-in-or-create-user-by-email).
|
168
168
|
#
|
169
169
|
# ### Add an email to an existing user
|
170
|
-
# This endpoint also allows you to add a new email to an existing Stytch User. Including a `user_id`, `session_token`, or `session_jwt` in
|
171
|
-
#
|
172
|
-
# Adding a new email to an existing Stytch User requires the user to be present and validate the email via magic link. This requirement is in place to prevent account takeover attacks.
|
170
|
+
# This endpoint also allows you to add a new email address to an existing Stytch User. Including a `user_id`, `session_token`, or `session_jwt` in your Send Magic Link by email request will add the new, unverified email address to the existing Stytch User. Upon successful authentication, the email address will be marked as verified.
|
173
171
|
#
|
174
172
|
# ### Next steps
|
175
173
|
# The user is emailed a magic link which redirects them to the provided [redirect URL](https://stytch.com/docs/guides/magic-links/email-magic-links/redirect-routing). Collect the `token` from the URL query parameters, and call [Authenticate magic link](https://stytch.com/docs/api/authenticate-magic-link) to complete authentication.
|
data/lib/stytch/otps.rb
CHANGED
@@ -131,9 +131,7 @@ module Stytch
|
|
131
131
|
#
|
132
132
|
# ### Add a phone number to an existing user
|
133
133
|
#
|
134
|
-
# This endpoint also allows you to add a new phone number to an existing Stytch User. Including a `user_id`, `session_token`, or `session_jwt` in
|
135
|
-
#
|
136
|
-
# Adding a new phone number to an existing Stytch User requires the user to be present and validate the phone number via OTP. This requirement is in place to prevent account takeover attacks.
|
134
|
+
# This endpoint also allows you to add a new phone number to an existing Stytch User. Including a `user_id`, `session_token`, or `session_jwt` in your Send one-time passcode by SMS request will add the new, unverified phone number to the existing Stytch User. Upon successful authentication, the phone number will be marked as verified.
|
137
135
|
#
|
138
136
|
# ### Next steps
|
139
137
|
#
|
@@ -289,9 +287,7 @@ module Stytch
|
|
289
287
|
#
|
290
288
|
# ### Add a phone number to an existing user
|
291
289
|
#
|
292
|
-
# This endpoint also allows you to add a new phone number to an existing Stytch User. Including a `user_id`, `session_token`, or `session_jwt` in
|
293
|
-
#
|
294
|
-
# Adding a new phone number to an existing Stytch User requires the user to be present and validate the phone number via OTP. This requirement is in place to prevent account takeover attacks.
|
290
|
+
# This endpoint also allows you to add a new phone number to an existing Stytch User. Including a `user_id`, `session_token`, or `session_jwt` in your Send one-time passcode by WhatsApp request will add the new, unverified phone number to the existing Stytch User. Upon successful authentication, the phone number will be marked as verified.
|
295
291
|
#
|
296
292
|
# ### Next steps
|
297
293
|
#
|
@@ -442,9 +438,7 @@ module Stytch
|
|
442
438
|
# Send a One-Time Passcode (OTP) to a User using their email. If you'd like to create a user and send them a passcode with one request, use our [log in or create endpoint](https://stytch.com/docs/api/log-in-or-create-user-by-email-otp).
|
443
439
|
#
|
444
440
|
# ### Add an email to an existing user
|
445
|
-
# This endpoint also allows you to add a new email to an existing Stytch User. Including a `user_id`, `session_token`, or `session_jwt` in
|
446
|
-
#
|
447
|
-
# Adding a new email to an existing Stytch User requires the User to be present and validate the email via OTP. This requirement is in place to prevent account takeover attacks.
|
441
|
+
# This endpoint also allows you to add a new email address to an existing Stytch User. Including a `user_id`, `session_token`, or `session_jwt` in your Send one-time passcode by email request will add the new, unverified email address to the existing Stytch User. Upon successful authentication, the email address will be marked as verified.
|
448
442
|
#
|
449
443
|
# ### Next steps
|
450
444
|
# Collect the OTP which was delivered to the user. Call [Authenticate OTP](https://stytch.com/docs/api/authenticate-otp) using the OTP `code` along with the `phone_id` found in the response as the `method_id`.
|
data/lib/stytch/users.rb
CHANGED
@@ -196,7 +196,7 @@ module Stytch
|
|
196
196
|
|
197
197
|
# Update a User's attributes.
|
198
198
|
#
|
199
|
-
# **Note:** In order to add a new email address or phone number to an existing User object, pass the new email address or phone number into the respective `/send` endpoint for the authentication method of your choice. If you specify the existing User's `user_id` while calling the `/send` endpoint, the new email address or phone number will be added to the existing User object
|
199
|
+
# **Note:** In order to add a new email address or phone number to an existing User object, pass the new email address or phone number into the respective `/send` endpoint for the authentication method of your choice. If you specify the existing User's `user_id` while calling the `/send` endpoint, the new, unverified email address or phone number will be added to the existing User object. Upon successful authentication, the email address or phone number will be marked as verified. We require this process to guard against an account takeover vulnerability.
|
200
200
|
#
|
201
201
|
# == Parameters:
|
202
202
|
# user_id::
|
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: 6.
|
4
|
+
version: 6.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- stytch
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-08-
|
11
|
+
date: 2023-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|