shopify_api 14.1.0 → 14.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2a0006cbbd93fb9880c4677510cd1223b6119c18176f7fc821c56f46d9220eb2
4
- data.tar.gz: 6b1bddbea59b7255f64659ec45cf2d9cd2e4fccf5aaf4a8804d526e37ff0a79c
3
+ metadata.gz: 0f2fd17eb9b42d6054e8b676c5d446cbc9890b7156f5c4b402a5efb776ad1421
4
+ data.tar.gz: 1deefc0fdcc79f57b70fb1fbeb2072916847b8d68c614b4b150dafd86f0ff6d5
5
5
  SHA512:
6
- metadata.gz: 888a1c8560873f27a0d4c73460ab15145410392c6d35818b728e81a5e10813da1032e6638aed8445611dfc46fb2fa08e9afddaf2f54ca762c1a534725d571dc4
7
- data.tar.gz: 79bbf5792589e217f4bae76db4d31a9d5b6c9b5e516c200037fd7d624f71a2f462015f264faf378244b73c661de76cbc2f751c278a0c4a60eb61c4b381c7c034
6
+ metadata.gz: 3cfdd1a407afb83e8557d607c65dd74322a7ca944fe58b2b42d68a911917442f51c78a0a7e59759a4fca59ae063c7af253ad8a297614a409621c52e0baf60ee6
7
+ data.tar.gz: e218a6a5c77d9de8e3b0a755c0bcb1b4941bb5cfba503564ffa4ca0a59c19b76e8c0cb56cb1ee458091bd43004fa3b16c200fa4696b058a0b90c9c3475bd37d0
data/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ Note: For changes to the API, see https://shopify.dev/changelog?filter=api
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 14.3.0
8
+ - [#1312](https://github.com/Shopify/shopify-api-ruby/pull/1312) Use same leeway for `exp` and `nbf` when parsing JWT
9
+ - [#1314](https://github.com/Shopify/shopify-api-ruby/pull/1314)
10
+ - Add new session util method `SessionUtils::session_id_from_shopify_id_token`
11
+ - `SessionUtils::current_session_id` now accepts shopify Id token in the format of `Bearer this_token` or just `this_token`
12
+ - [#1315](https://github.com/Shopify/shopify-api-ruby/pull/1315) Add helper/alias methods to `ShopifyAPI::Auth::JwtPayload`:
13
+ - `shopify_domain` alias for `shop` - returns the sanitized shop domain
14
+ - `shopify_user_id` - returns the user Id (`sub`) as an Integer value
15
+ - `expires_at` alias for `exp` - returns the expiration time
16
+
17
+ ## 14.2.0
18
+ - [#1309](https://github.com/Shopify/shopify-api-ruby/pull/1309) Add `Session#copy_attributes_from` method
7
19
 
8
20
  ## 14.1.0
9
21
  - [#1071](https://github.com/Shopify/shopify-api-ruby/issues/1071) Fix FulfillmentEvent class types
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shopify_api (14.1.0)
4
+ shopify_api (14.3.0)
5
5
  activesupport
6
6
  concurrent-ruby
7
7
  hash_diff
@@ -116,7 +116,7 @@ GEM
116
116
  thor (>= 0.19.2)
117
117
  syntax_tree (6.2.0)
118
118
  prettier_print (>= 1.2.0)
119
- tapioca (0.13.1)
119
+ tapioca (0.13.3)
120
120
  bundler (>= 2.2.25)
121
121
  netrc (>= 0.11.0)
122
122
  parallel (>= 1.21.0)
@@ -46,13 +46,28 @@ Session persistence is handled by the [ShopifyApp](https://github.com/Shopify/sh
46
46
  #### Cookie
47
47
  Cookie based authentication is not supported for embedded apps due to browsers dropping support for third party cookies due to security concerns. Non-embedded apps are able to use cookies for session storage/retrieval.
48
48
 
49
- For *non-embedded* apps, you can pass the cookies into `ShopifyAPI::Utils::SessionUtils.current_session_id(nil, cookies, true)` for online (user) sessions or `ShopifyAPI::Utils::SessionUtils.current_session_id(nil, cookies, false)` for offline (store) sessions.
49
+ For *non-embedded* apps, you can pass the cookies into:
50
+ - `ShopifyAPI::Utils::SessionUtils.current_session_id(nil, cookies, true)` for online (user) sessions or
51
+ - `ShopifyAPI::Utils::SessionUtils.current_session_id(nil, cookies, false)` for offline (store) sessions.
50
52
 
51
53
  #### Getting Session ID From Embedded Requests
52
- For *embedded* apps, you can pass the auth header into `ShopifyAPI::Utils::SessionUtils.current_session_id(auth_header, nil, true)` for online (user) sessions or `ShopifyAPI::Utils::SessionUtils.current_session_id(auth_header, nil, false)` for offline (store) sessions. This function needs an `auth_header` which is the `HTTP_AUTHORIZATION` header.
53
54
 
54
55
  If your app uses client side rendering instead of server side rendering, you will need to use App Bridge's [authenticatedFetch](https://shopify.dev/docs/apps/auth/oauth/session-tokens/getting-started) to make authenticated API requests from the client.
55
56
 
57
+ For *embedded* apps:
58
+
59
+ If you have an `HTTP_AUTHORIZATION` header or `id_token` from the request URL params , you can pass that as `shopify_id_token` into:
60
+ - `ShopifyAPI::Utils::SessionUtils.current_session_id(shopify_id_token, nil, true)` for online (user) sessions or
61
+ - `ShopifyAPI::Utils::SessionUtils.current_session_id(shopify_id_token, nil, false)` for offline (store) sessions.
62
+
63
+ `current_session_id` accepts shopify_id_token in the format of `Bearer this_token` or just `this_token`.
64
+
65
+ You can also use this method to get session ID:
66
+ - `ShopifyAPI::Utils::SessionUtils::session_id_from_shopify_id_token(id_token: id_token, online: true)` for online (user) sessions or
67
+ - `ShopifyAPI::Utils::SessionUtils::session_id_from_shopify_id_token(id_token: id_token, online: false)` for offline (store) sessions.
68
+
69
+ `session_id_from_shopify_id_token` does **NOT** accept shopify_id_token in the format of `Bearer this_token`, you must pass in `this_token`.
70
+
56
71
  #### Start Making Authenticated Shopify Requests
57
72
 
58
73
  You can now start making authenticated Shopify API calls using the Admin [REST](usage/rest.md) or [GraphQL](usage/graphql.md) Clients or the [Storefront GraphQL Client](usage/graphql_storefront.md).
@@ -6,7 +6,8 @@ module ShopifyAPI
6
6
  class JwtPayload
7
7
  extend T::Sig
8
8
 
9
- JWT_EXPIRATION_LEEWAY = 10
9
+ JWT_LEEWAY = 10
10
+ JWT_EXPIRATION_LEEWAY = JWT_LEEWAY
10
11
 
11
12
  sig { returns(String) }
12
13
  attr_reader :iss, :dest, :aud, :sub, :jti, :sid
@@ -14,6 +15,8 @@ module ShopifyAPI
14
15
  sig { returns(Integer) }
15
16
  attr_reader :exp, :nbf, :iat
16
17
 
18
+ alias_method :expire_at, :exp
19
+
17
20
  sig { params(token: String).void }
18
21
  def initialize(token)
19
22
  payload_hash = begin
@@ -42,6 +45,12 @@ module ShopifyAPI
42
45
  def shop
43
46
  @dest.gsub("https://", "")
44
47
  end
48
+ alias_method :shopify_domain, :shop
49
+
50
+ sig { returns(Integer) }
51
+ def shopify_user_id
52
+ @sub.to_i
53
+ end
45
54
 
46
55
  # TODO: Remove before releasing v11
47
56
  sig { params(shop: String).returns(T::Boolean) }
@@ -73,8 +82,7 @@ module ShopifyAPI
73
82
 
74
83
  sig { params(token: String, api_secret_key: String).returns(T::Hash[String, T.untyped]) }
75
84
  def decode_token(token, api_secret_key)
76
- JWT.decode(token, api_secret_key, true,
77
- { exp_leeway: JWT_EXPIRATION_LEEWAY, algorithm: "HS256" })[0]
85
+ JWT.decode(token, api_secret_key, true, leeway: JWT_LEEWAY, algorithm: "HS256")[0]
78
86
  rescue JWT::DecodeError => err
79
87
  raise ShopifyAPI::Errors::InvalidJwtTokenError, "Error decoding session token: #{err.message}"
80
88
  end
@@ -121,6 +121,17 @@ module ShopifyAPI
121
121
  end
122
122
  end
123
123
 
124
+ sig { params(other: Session).returns(Session) }
125
+ def copy_attributes_from(other)
126
+ JSON.parse(other.serialize).keys.each do |key|
127
+ next if key.include?("^")
128
+
129
+ variable_name = "@#{key}"
130
+ instance_variable_set(variable_name, other.instance_variable_get(variable_name))
131
+ end
132
+ self
133
+ end
134
+
124
135
  sig { returns(String) }
125
136
  def serialize
126
137
  Oj.dump(self)
@@ -11,28 +11,16 @@ module ShopifyAPI
11
11
 
12
12
  sig do
13
13
  params(
14
- auth_header: T.nilable(String),
14
+ shopify_id_token: T.nilable(String),
15
15
  cookies: T.nilable(T::Hash[String, String]),
16
16
  online: T::Boolean,
17
17
  ).returns(T.nilable(String))
18
18
  end
19
- def current_session_id(auth_header, cookies, online)
19
+ def current_session_id(shopify_id_token, cookies, online)
20
20
  if Context.embedded?
21
- if auth_header
22
- matches = auth_header.match(/^Bearer (.+)$/)
23
- unless matches
24
- ShopifyAPI::Logger.warn("Missing Bearer token in authorization header")
25
- raise Errors::MissingJwtTokenError, "Missing Bearer token in authorization header"
26
- end
27
-
28
- jwt_payload = Auth::JwtPayload.new(T.must(matches[1]))
29
- shop = jwt_payload.shop
30
-
31
- if online
32
- jwt_session_id(shop, jwt_payload.sub)
33
- else
34
- offline_session_id(shop)
35
- end
21
+ if shopify_id_token
22
+ id_token = shopify_id_token.gsub("Bearer ", "")
23
+ session_id_from_shopify_id_token(id_token: id_token, online: online)
36
24
  else
37
25
  # falling back to session cookie
38
26
  raise Errors::CookieNotFoundError, "JWT token or Session cookie not found for app" unless
@@ -48,6 +36,25 @@ module ShopifyAPI
48
36
  end
49
37
  end
50
38
 
39
+ sig do
40
+ params(
41
+ id_token: T.nilable(String),
42
+ online: T::Boolean,
43
+ ).returns(String)
44
+ end
45
+ def session_id_from_shopify_id_token(id_token:, online:)
46
+ raise Errors::MissingJwtTokenError, "Missing Shopify ID Token" if id_token.nil? || id_token.empty?
47
+
48
+ payload = Auth::JwtPayload.new(id_token)
49
+ shop = payload.shop
50
+
51
+ if online
52
+ jwt_session_id(shop, payload.sub)
53
+ else
54
+ offline_session_id(shop)
55
+ end
56
+ end
57
+
51
58
  sig { params(shop: String, user_id: String).returns(String) }
52
59
  def jwt_session_id(shop, user_id)
53
60
  "#{shop}_#{user_id}"
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module ShopifyAPI
5
- VERSION = "14.1.0"
5
+ VERSION = "14.3.0"
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 14.1.0
4
+ version: 14.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-08 00:00:00.000000000 Z
11
+ date: 2024-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -1009,7 +1009,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1009
1009
  - !ruby/object:Gem::Version
1010
1010
  version: '0'
1011
1011
  requirements: []
1012
- rubygems_version: 3.5.7
1012
+ rubygems_version: 3.5.9
1013
1013
  signing_key:
1014
1014
  specification_version: 4
1015
1015
  summary: The gem for accessing the Shopify API