diff --git a/lib/shopify_app/session/jwt.rb b/lib/shopify_app/session/jwt.rb index b865f6e5b..19e345560 100644 --- a/lib/shopify_app/session/jwt.rb +++ b/lib/shopify_app/session/jwt.rb @@ -8,6 +8,8 @@ class MismatchedHostsError < StandardError; end class InvalidAudienceError < StandardError; end + NBF_TOLERANCE = 5.seconds + WARN_EXCEPTIONS = [ ::JWT::DecodeError, ::JWT::ExpiredSignature, @@ -46,7 +48,7 @@ def set_payload end def parse_token_data(secret, old_secret) - ::JWT.decode(@token, secret, true, { algorithm: "HS256" }) + ::JWT.decode(@token, secret, true, { nbf_leeway: NBF_TOLERANCE, algorithm: "HS256" }) rescue ::JWT::VerificationError raise unless old_secret diff --git a/test/shopify_app/session/jwt_test.rb b/test/shopify_app/session/jwt_test.rb index 6a67e8feb..ed7af4335 100644 --- a/test/shopify_app/session/jwt_test.rb +++ b/test/shopify_app/session/jwt_test.rb @@ -25,6 +25,15 @@ class JWTTest < ActiveSupport::TestCase assert_equal TEST_JWT_EXPIRE_AT.to_i, jwt.expire_at end + test "#shopify_domain, #shopify_user_id and #expire_at are returned with NBF tolerances" do + p = payload(nbf: (JWT::NBF_TOLERANCE - 1.second).from_now) + jwt = JWT.new(token(p)) + + assert_equal TEST_SANITIZED_SHOPIFY_DOMAIN, jwt.shopify_domain + assert_equal TEST_USER_ID.to_i, jwt.shopify_user_id + assert_equal TEST_JWT_EXPIRE_AT.to_i, jwt.expire_at + end + test "#shopify_domain and #shopify_user_id are returned using the old secret" do p = payload t = ::JWT.encode(p, ShopifyApp.configuration.old_secret, "HS256") @@ -97,7 +106,7 @@ class JWTTest < ActiveSupport::TestCase test "#shopify_domain and #shopify_user_id are nil if 'nbf' claim is in the future" do expect_jwt_error(::JWT::ImmatureSignature, "Signature nbf has not been reached") - p = payload(nbf: 1.day.from_now) + p = payload(nbf: (JWT::NBF_TOLERANCE + 3.second).from_now) jwt = JWT.new(token(p)) assert_nil jwt.shopify_domain