stytch 6.4.0 → 6.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +13 -0
- data/.rubocop.yml +21 -0
- data/DEVELOPMENT.md +5 -2
- data/lib/stytch/b2b_client.rb +1 -1
- data/lib/stytch/b2b_organizations.rb +1 -4
- data/lib/stytch/b2b_passwords.rb +55 -11
- data/lib/stytch/b2b_sessions.rb +105 -1
- data/lib/stytch/magic_links.rb +8 -6
- data/lib/stytch/oauth.rb +5 -1
- data/lib/stytch/otps.rb +3 -9
- data/lib/stytch/passwords.rb +39 -6
- data/lib/stytch/users.rb +1 -1
- data/lib/stytch/version.rb +1 -1
- data/stytch.gemspec +2 -0
- metadata +31 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b550936fb7076aad0eb10a1551f50440e8855c5042e6d1173a68d5eaf8df7b7d
|
4
|
+
data.tar.gz: afa5981979e47b49868ce2be6f701d3d94102365f2565e8f1c42889d548b8af5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48fb733f974b3f66b0f11d62aa0215ddf162f8d3f715d63c750e3820c261fffb33a1a04668370b66b28f2fb5d7311bd0608d3b6cc421d48629b93bb287dba814
|
7
|
+
data.tar.gz: 6f05e0e6dad871dd162c45007c2e9cf8a303b721d8a81aa1f74dfbe785f317cf14cabdeedfce2abe2d42523773e260998a372644c4fa8da7f1e362b3f186815c
|
data/.github/workflows/ruby.yml
CHANGED
@@ -26,3 +26,16 @@ jobs:
|
|
26
26
|
bundler-cache: true
|
27
27
|
|
28
28
|
- run: bundle exec rspec
|
29
|
+
|
30
|
+
lint:
|
31
|
+
runs-on: ubuntu-latest
|
32
|
+
steps:
|
33
|
+
- uses: actions/checkout@v3
|
34
|
+
|
35
|
+
- uses: ruby/setup-ruby@v1
|
36
|
+
with:
|
37
|
+
# Match the minimum supported Ruby version in the gemspec.
|
38
|
+
ruby-version: '2.7'
|
39
|
+
bundler-cache: true
|
40
|
+
|
41
|
+
- run: bundle exec rubocop
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require:
|
2
|
+
- rubocop-rspec
|
3
|
+
|
4
|
+
AllCops:
|
5
|
+
NewCops: disable
|
6
|
+
# The target Ruby version must match the one in stytch.gemspec.
|
7
|
+
TargetRubyVersion: 2.7
|
8
|
+
|
9
|
+
Layout/LineLength: { Enabled: false }
|
10
|
+
|
11
|
+
Metrics: { Enabled: false }
|
12
|
+
|
13
|
+
Style/Documentation: { Enabled: false }
|
14
|
+
Style/For: { Enabled: false }
|
15
|
+
Style/FrozenStringLiteralComment: { Enabled: false }
|
16
|
+
Style/NumericPredicate: { Enabled: false }
|
17
|
+
Style/StringConcatenation: { Enabled: false }
|
18
|
+
|
19
|
+
RSpec/DescribedClass: { Enabled: false }
|
20
|
+
RSpec/ExampleLength: { Enabled: false }
|
21
|
+
RSpec/MultipleExpectations: { Enabled: false }
|
data/DEVELOPMENT.md
CHANGED
@@ -5,7 +5,9 @@ Thanks for contributing to Stytch's Ruby library! If you run into trouble, find
|
|
5
5
|
## Setup
|
6
6
|
|
7
7
|
1. Clone this repo.
|
8
|
-
2.
|
8
|
+
2. Install development dependencies using [Bundler]: `bundle install`
|
9
|
+
|
10
|
+
To test your changes locally in another project, update your `GEMFILE` with `gem 'stytch', path: '../stytch'` where `../stytch` is the path to your cloned copy of stytch-ruby.
|
9
11
|
|
10
12
|
## Issues and Pull Requests
|
11
13
|
|
@@ -15,4 +17,5 @@ If you have non-trivial changes you'd like us to incorporate, please open an iss
|
|
15
17
|
|
16
18
|
When you're ready for someone to look at your issue or PR, assign `@stytchauth/client-libraries` (GitHub should do this automatically). If we don't acknowledge it within one business day, please escalate it by tagging `@stytchauth/engineering` in a comment or letting us know in [Slack].
|
17
19
|
|
18
|
-
[
|
20
|
+
[Bundler]: https://bundler.io/
|
21
|
+
[Slack]: https://join.slack.com/t/stytch/shared_invite/zt-nil4wo92-jApJ9Cl32cJbEd9esKkvyg
|
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
|
@@ -280,10 +280,7 @@ module StytchB2B
|
|
280
280
|
request[:trusted_metadata] = trusted_metadata unless trusted_metadata.nil?
|
281
281
|
request[:sso_default_connection_id] = sso_default_connection_id unless sso_default_connection_id.nil?
|
282
282
|
request[:sso_jit_provisioning] = sso_jit_provisioning unless sso_jit_provisioning.nil?
|
283
|
-
unless sso_jit_provisioning_allowed_connections.nil?
|
284
|
-
request[:sso_jit_provisioning_allowed_connections] =
|
285
|
-
sso_jit_provisioning_allowed_connections
|
286
|
-
end
|
283
|
+
request[:sso_jit_provisioning_allowed_connections] = sso_jit_provisioning_allowed_connections unless sso_jit_provisioning_allowed_connections.nil?
|
287
284
|
request[:email_allowed_domains] = email_allowed_domains unless email_allowed_domains.nil?
|
288
285
|
request[:email_jit_provisioning] = email_jit_provisioning unless email_jit_provisioning.nil?
|
289
286
|
request[:email_invites] = email_invites unless email_invites.nil?
|
data/lib/stytch/b2b_passwords.rb
CHANGED
@@ -180,12 +180,9 @@ module StytchB2B
|
|
180
180
|
post_request('/v1/b2b/passwords/migrate', request)
|
181
181
|
end
|
182
182
|
|
183
|
-
# 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.
|
184
|
-
#
|
185
|
-
#
|
186
|
-
# * A member that has previously authenticated with email/password uses a passwordless authentication method tied to the same email address (e.g. Magic Links) for the first time. Any subsequent email/password authentication attempt will result in this error.
|
187
|
-
# * We force a password reset in this instance in order to safely deduplicate the account by email address, without introducing the risk of a pre-hijack account takeover attack.
|
188
|
-
# * Imagine a bad actor creates many accounts using passwords and the known email addresses of their victims. If a victim comes to the site and logs in for the first time with an email-based passwordless authentication method then both the victim and the bad actor have credentials to access to the same account. To prevent this, any further email/password login attempts first require a password reset which can only be accomplished by someone with access to the underlying email address.
|
183
|
+
# 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.
|
184
|
+
#
|
185
|
+
# If you have breach detection during authentication enabled in your [password strength policy](https://stytch.com/docs/b2b/guides/passwords/strength-policies) 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.
|
189
186
|
#
|
190
187
|
# 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.
|
191
188
|
# 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.
|
@@ -382,10 +379,7 @@ module StytchB2B
|
|
382
379
|
email_address: email_address
|
383
380
|
}
|
384
381
|
request[:reset_password_redirect_url] = reset_password_redirect_url unless reset_password_redirect_url.nil?
|
385
|
-
unless reset_password_expiration_minutes.nil?
|
386
|
-
request[:reset_password_expiration_minutes] =
|
387
|
-
reset_password_expiration_minutes
|
388
|
-
end
|
382
|
+
request[:reset_password_expiration_minutes] = reset_password_expiration_minutes unless reset_password_expiration_minutes.nil?
|
389
383
|
request[:code_challenge] = code_challenge unless code_challenge.nil?
|
390
384
|
request[:login_redirect_url] = login_redirect_url unless login_redirect_url.nil?
|
391
385
|
request[:locale] = locale unless locale.nil?
|
@@ -543,6 +537,32 @@ module StytchB2B
|
|
543
537
|
# session_jwt::
|
544
538
|
# The JSON Web Token (JWT) for a given Stytch Session.
|
545
539
|
# The type of this field is nilable +String+.
|
540
|
+
# session_duration_minutes::
|
541
|
+
# Set the session lifetime to be this many minutes from now. This will start a new session if one doesn't already exist,
|
542
|
+
# returning both an opaque `session_token` and `session_jwt` for this session. Remember that the `session_jwt` will have a fixed lifetime of
|
543
|
+
# five minutes regardless of the underlying session duration, and will need to be refreshed over time.
|
544
|
+
#
|
545
|
+
# This value must be a minimum of 5 and a maximum of 527040 minutes (366 days).
|
546
|
+
#
|
547
|
+
# If a `session_token` or `session_jwt` is provided then a successful authentication will continue to extend the session this many minutes.
|
548
|
+
#
|
549
|
+
# If the `session_duration_minutes` parameter is not specified, a Stytch session will be created with a 60 minute duration. If you don't want
|
550
|
+
# to use the Stytch session product, you can ignore the session fields in the response.
|
551
|
+
# The type of this field is nilable +Integer+.
|
552
|
+
# session_custom_claims::
|
553
|
+
# Add a custom claims map to the Session being authenticated. Claims are only created if a Session is initialized by providing a value in
|
554
|
+
# `session_duration_minutes`. Claims will be included on the Session object and in the JWT. To update a key in an existing Session, supply a new value. To
|
555
|
+
# delete a key, supply a null value. Custom claims made with reserved claims (`iss`, `sub`, `aud`, `exp`, `nbf`, `iat`, `jti`) will be ignored.
|
556
|
+
# Total custom claims size cannot exceed four kilobytes.
|
557
|
+
# The type of this field is nilable +object+.
|
558
|
+
# locale::
|
559
|
+
# Used to determine which language to use when sending the user this delivery method. Parameter is a [IETF BCP 47 language tag](https://www.w3.org/International/articles/language-tags/), e.g. `"en"`.
|
560
|
+
#
|
561
|
+
# Currently supported languages are English (`"en"`), Spanish (`"es"`), and Brazilian Portuguese (`"pt-br"`); if no value is provided, the copy defaults to English.
|
562
|
+
#
|
563
|
+
# Request support for additional languages [here](https://docs.google.com/forms/d/e/1FAIpQLScZSpAu_m2AmLXRT3F3kap-s_mcV6UTBitYn6CdyWP0-o7YjQ/viewform?usp=sf_link")!
|
564
|
+
#
|
565
|
+
# The type of this field is nilable +ResetRequestLocale+ (string enum).
|
546
566
|
#
|
547
567
|
# == Returns:
|
548
568
|
# An object with the following fields:
|
@@ -558,17 +578,38 @@ module StytchB2B
|
|
558
578
|
# organization::
|
559
579
|
# The [Organization object](https://stytch.com/docs/b2b/api/organization-object).
|
560
580
|
# The type of this field is +Organization+ (+object+).
|
581
|
+
# session_token::
|
582
|
+
# A secret token for a given Stytch Session.
|
583
|
+
# The type of this field is +String+.
|
584
|
+
# session_jwt::
|
585
|
+
# The JSON Web Token (JWT) for a given Stytch Session.
|
586
|
+
# The type of this field is +String+.
|
587
|
+
# intermediate_session_token::
|
588
|
+
# The Intermediate Session Token. This token does not necessarily belong to a specific instance of a Member, but represents a bag of factors that may be converted to a member session.
|
589
|
+
# The token can be used with the [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms) to complete an MFA flow;
|
590
|
+
# the [Exchange Intermediate Session endpoint](https://stytch.com/docs/b2b/api/exchange-intermediate-session) to join a specific Organization that allows the factors represented by the intermediate session token;
|
591
|
+
# or the [Create Organization via Discovery endpoint](https://stytch.com/docs/b2b/api/create-organization-via-discovery) to create a new Organization and Member.
|
592
|
+
# The type of this field is +String+.
|
593
|
+
# member_authenticated::
|
594
|
+
# Indicates whether the Member is fully authenticated. If false, the Member needs to complete an MFA step to log in to the Organization.
|
595
|
+
# The type of this field is +Boolean+.
|
561
596
|
# status_code::
|
562
597
|
# 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.
|
563
598
|
# The type of this field is +Integer+.
|
564
599
|
# member_session::
|
565
600
|
# The [Session object](https://stytch.com/docs/b2b/api/session-object).
|
566
601
|
# The type of this field is nilable +MemberSession+ (+object+).
|
602
|
+
# mfa_required::
|
603
|
+
# Information about the MFA requirements of the Organization and the Member's options for fulfilling MFA.
|
604
|
+
# The type of this field is nilable +MfaRequired+ (+object+).
|
567
605
|
def reset(
|
568
606
|
organization_id:,
|
569
607
|
password:,
|
570
608
|
session_token: nil,
|
571
|
-
session_jwt: nil
|
609
|
+
session_jwt: nil,
|
610
|
+
session_duration_minutes: nil,
|
611
|
+
session_custom_claims: nil,
|
612
|
+
locale: nil
|
572
613
|
)
|
573
614
|
request = {
|
574
615
|
organization_id: organization_id,
|
@@ -576,6 +617,9 @@ module StytchB2B
|
|
576
617
|
}
|
577
618
|
request[:session_token] = session_token unless session_token.nil?
|
578
619
|
request[:session_jwt] = session_jwt unless session_jwt.nil?
|
620
|
+
request[:session_duration_minutes] = session_duration_minutes unless session_duration_minutes.nil?
|
621
|
+
request[:session_custom_claims] = session_custom_claims unless session_custom_claims.nil?
|
622
|
+
request[:locale] = locale unless locale.nil?
|
579
623
|
|
580
624
|
post_request('/v1/b2b/passwords/session/reset', request)
|
581
625
|
end
|
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
@@ -23,7 +23,11 @@ module Stytch
|
|
23
23
|
#
|
24
24
|
# == Parameters:
|
25
25
|
# token::
|
26
|
-
# The token
|
26
|
+
# The Magic Link `token` from the `?token=` query parameter in the URL.
|
27
|
+
#
|
28
|
+
# The redirect URL will look like `https://example.com/authenticate?stytch_token_type=magic_links&token=rM_kw42CWBhsHLF62V75jELMbvJ87njMe3tFVj7Qupu7`
|
29
|
+
#
|
30
|
+
# In the redirect URL, the `stytch_token_type` will be `magic_link`. See [here](https://stytch.com/docs/guides/dashboard/redirect-urls) for more detail.
|
27
31
|
# The type of this field is +String+.
|
28
32
|
# attributes::
|
29
33
|
# Provided attributes help with fraud detection.
|
@@ -167,9 +171,7 @@ module Stytch
|
|
167
171
|
# 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
172
|
#
|
169
173
|
# ### 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.
|
174
|
+
# 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. If the user successfully authenticates within 5 minutes, the new email address will be marked as verified and remain permanently on the existing Stytch User. Otherwise, it will be removed from the User object, and any subsequent login requests using that email address will create a new User.
|
173
175
|
#
|
174
176
|
# ### Next steps
|
175
177
|
# 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.
|
@@ -271,7 +273,7 @@ module Stytch
|
|
271
273
|
# Send either a login or signup Magic Link to the User based on if the email is associated with a User already. A new or pending User will receive a signup Magic Link. An active User will receive a login Magic Link. For more information on how to control the status your Users are created in see the `create_user_as_pending` flag.
|
272
274
|
#
|
273
275
|
# ### Next steps
|
274
|
-
# The User is emailed a Magic Link which redirects them to the provided [redirect URL](https://stytch.com/docs/magic-links
|
276
|
+
# 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.
|
275
277
|
#
|
276
278
|
# == Parameters:
|
277
279
|
# email::
|
@@ -367,7 +369,7 @@ module Stytch
|
|
367
369
|
# Create a User and send an invite Magic Link to the provided `email`. The User will be created with a `pending` status until they click the Magic Link in the invite email.
|
368
370
|
#
|
369
371
|
# ### Next steps
|
370
|
-
# The User is emailed a Magic Link which redirects them to the provided [redirect URL](https://stytch.com/docs/magic-links
|
372
|
+
# 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.
|
371
373
|
#
|
372
374
|
# == Parameters:
|
373
375
|
# email::
|
data/lib/stytch/oauth.rb
CHANGED
@@ -67,7 +67,11 @@ module Stytch
|
|
67
67
|
#
|
68
68
|
# == Parameters:
|
69
69
|
# token::
|
70
|
-
# The token
|
70
|
+
# The OAuth `token` from the `?token=` query parameter in the URL.
|
71
|
+
#
|
72
|
+
# The redirect URL will look like `https://example.com/authenticate?stytch_token_type=oauth&token=rM_kw42CWBhsHLF62V75jELMbvJ87njMe3tFVj7Qupu7`
|
73
|
+
#
|
74
|
+
# In the redirect URL, the `stytch_token_type` will be `oauth`. See [here](https://stytch.com/docs/guides/dashboard/redirect-urls) for more detail.
|
71
75
|
# The type of this field is +String+.
|
72
76
|
# session_token::
|
73
77
|
# Reuse an existing session instead of creating a new one. If you provide us with a `session_token`, then we'll update the session represented by this session token with this OAuth factor. If this `session_token` belongs to a different user than the OAuth token, the session_jwt will be ignored. This endpoint will error if both `session_token` and `session_jwt` are provided.
|
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. If the user successfully authenticates within 5 minutes, the new phone number will be marked as verified and remain permanently on the existing Stytch User. Otherwise, it will be removed from the User object, and any subsequent login requests using that phone number will create a new User.
|
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. If the user successfully authenticates within 5 minutes, the new phone number will be marked as verified and remain permanently on the existing Stytch User. Otherwise, it will be removed from the User object, and any subsequent login requests using that phone number will create a new User.
|
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. If the user successfully authenticates within 5 minutes, the new email address will be marked as verified and remain permanently on the existing Stytch User. Otherwise, it will be removed from the User object, and any subsequent login requests using that email address will create a new User.
|
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/passwords.rb
CHANGED
@@ -419,10 +419,7 @@ module Stytch
|
|
419
419
|
email: email
|
420
420
|
}
|
421
421
|
request[:reset_password_redirect_url] = reset_password_redirect_url unless reset_password_redirect_url.nil?
|
422
|
-
unless reset_password_expiration_minutes.nil?
|
423
|
-
request[:reset_password_expiration_minutes] =
|
424
|
-
reset_password_expiration_minutes
|
425
|
-
end
|
422
|
+
request[:reset_password_expiration_minutes] = reset_password_expiration_minutes unless reset_password_expiration_minutes.nil?
|
426
423
|
request[:code_challenge] = code_challenge unless code_challenge.nil?
|
427
424
|
request[:attributes] = attributes unless attributes.nil?
|
428
425
|
request[:login_redirect_url] = login_redirect_url unless login_redirect_url.nil?
|
@@ -436,9 +433,15 @@ module Stytch
|
|
436
433
|
#
|
437
434
|
# The provided password needs to meet our password strength requirements, which can be checked in advance with the password strength endpoint. If the token and password are accepted, the password is securely stored for future authentication and the user is authenticated.
|
438
435
|
#
|
436
|
+
# Note that a successful password reset by email will revoke all active sessions for the `user_id`.
|
437
|
+
#
|
439
438
|
# == Parameters:
|
440
439
|
# token::
|
441
|
-
# The token
|
440
|
+
# The Passwords `token` from the `?token=` query parameter in the URL.
|
441
|
+
#
|
442
|
+
# In the redirect URL, the `stytch_token_type` will be `login` or `reset_password`.
|
443
|
+
#
|
444
|
+
# See examples and read more about redirect URLs [here](https://stytch.com/docs/guides/dashboard/redirect-urls).
|
442
445
|
# The type of this field is +String+.
|
443
446
|
# password::
|
444
447
|
# The password of the user
|
@@ -537,6 +540,8 @@ module Stytch
|
|
537
540
|
|
538
541
|
# Reset the User’s password using their existing password.
|
539
542
|
#
|
543
|
+
# Note that a successful password reset via an existing password will revoke all active sessions for the `user_id`.
|
544
|
+
#
|
540
545
|
# == Parameters:
|
541
546
|
# email::
|
542
547
|
# The email address of the end user.
|
@@ -628,6 +633,8 @@ module Stytch
|
|
628
633
|
|
629
634
|
# Reset the user’s password using their existing session. The endpoint will error if the session does not have a password, email magic link, or email OTP authentication factor that has been issued within the last 5 minutes. This endpoint requires either a `session_jwt` or `session_token` be included in the request.
|
630
635
|
#
|
636
|
+
# Note that a successful password reset via an existing session will revoke all active sessions for the `user_id`, except for the one used during the reset flow.
|
637
|
+
#
|
631
638
|
# == Parameters:
|
632
639
|
# password::
|
633
640
|
# The password of the user
|
@@ -638,6 +645,22 @@ module Stytch
|
|
638
645
|
# session_jwt::
|
639
646
|
# The `session_jwt` associated with a User's existing Session.
|
640
647
|
# The type of this field is nilable +String+.
|
648
|
+
# session_duration_minutes::
|
649
|
+
# Set the session lifetime to be this many minutes from now. This will start a new session if one doesn't already exist,
|
650
|
+
# returning both an opaque `session_token` and `session_jwt` for this session. Remember that the `session_jwt` will have a fixed lifetime of
|
651
|
+
# five minutes regardless of the underlying session duration, and will need to be refreshed over time.
|
652
|
+
#
|
653
|
+
# This value must be a minimum of 5 and a maximum of 527040 minutes (366 days).
|
654
|
+
#
|
655
|
+
# If a `session_token` or `session_jwt` is provided then a successful authentication will continue to extend the session this many minutes.
|
656
|
+
#
|
657
|
+
# If the `session_duration_minutes` parameter is not specified, a Stytch session will not be created.
|
658
|
+
# The type of this field is nilable +Integer+.
|
659
|
+
# session_custom_claims::
|
660
|
+
# Add a custom claims map to the Session being authenticated. Claims are only created if a Session is initialized by providing a value in `session_duration_minutes`. Claims will be included on the Session object and in the JWT. To update a key in an existing Session, supply a new value. To delete a key, supply a null value.
|
661
|
+
#
|
662
|
+
# Custom claims made with reserved claims ("iss", "sub", "aud", "exp", "nbf", "iat", "jti") will be ignored. Total custom claims size cannot exceed four kilobytes.
|
663
|
+
# The type of this field is nilable +object+.
|
641
664
|
#
|
642
665
|
# == Returns:
|
643
666
|
# An object with the following fields:
|
@@ -650,6 +673,12 @@ module Stytch
|
|
650
673
|
# user::
|
651
674
|
# 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.
|
652
675
|
# The type of this field is +User+ (+object+).
|
676
|
+
# session_token::
|
677
|
+
# A secret token for a given Stytch Session.
|
678
|
+
# The type of this field is +String+.
|
679
|
+
# session_jwt::
|
680
|
+
# The JSON Web Token (JWT) for a given Stytch Session.
|
681
|
+
# The type of this field is +String+.
|
653
682
|
# status_code::
|
654
683
|
# 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.
|
655
684
|
# The type of this field is +Integer+.
|
@@ -662,13 +691,17 @@ module Stytch
|
|
662
691
|
def reset(
|
663
692
|
password:,
|
664
693
|
session_token: nil,
|
665
|
-
session_jwt: nil
|
694
|
+
session_jwt: nil,
|
695
|
+
session_duration_minutes: nil,
|
696
|
+
session_custom_claims: nil
|
666
697
|
)
|
667
698
|
request = {
|
668
699
|
password: password
|
669
700
|
}
|
670
701
|
request[:session_token] = session_token unless session_token.nil?
|
671
702
|
request[:session_jwt] = session_jwt unless session_jwt.nil?
|
703
|
+
request[:session_duration_minutes] = session_duration_minutes unless session_duration_minutes.nil?
|
704
|
+
request[:session_custom_claims] = session_custom_claims unless session_custom_claims.nil?
|
672
705
|
|
673
706
|
post_request('/v1/passwords/session/reset', request)
|
674
707
|
end
|
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. If the user successfully authenticates within 5 minutes of the `/send` request, the new email address or phone number will be marked as verified and remain permanently on the existing Stytch User. Otherwise, it will be removed from the User object, and any subsequent login requests using that phone number will create a new User. We require this process to guard against an account takeover vulnerability.
|
200
200
|
#
|
201
201
|
# == Parameters:
|
202
202
|
# user_id::
|
data/lib/stytch/version.rb
CHANGED
data/stytch.gemspec
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.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- stytch
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -72,6 +72,34 @@ dependencies:
|
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: 3.11.0
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rubocop
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - '='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 1.56.3
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - '='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 1.56.3
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: rubocop-rspec
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - '='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 2.24.0
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - '='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 2.24.0
|
75
103
|
description:
|
76
104
|
email:
|
77
105
|
- support@stytch.com
|
@@ -84,6 +112,7 @@ files:
|
|
84
112
|
- ".github/workflows/ruby.yml"
|
85
113
|
- ".gitignore"
|
86
114
|
- ".rspec"
|
115
|
+
- ".rubocop.yml"
|
87
116
|
- ".travis.yml"
|
88
117
|
- CODEOWNERS
|
89
118
|
- CODE_OF_CONDUCT.md
|