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 +4 -4
- data/CHANGELOG.md +12 -0
- data/Gemfile.lock +2 -2
- data/docs/getting_started.md +17 -2
- data/lib/shopify_api/auth/jwt_payload.rb +11 -3
- data/lib/shopify_api/auth/session.rb +11 -0
- data/lib/shopify_api/utils/session_utils.rb +24 -17
- data/lib/shopify_api/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f2fd17eb9b42d6054e8b676c5d446cbc9890b7156f5c4b402a5efb776ad1421
|
4
|
+
data.tar.gz: 1deefc0fdcc79f57b70fb1fbeb2072916847b8d68c614b4b150dafd86f0ff6d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
119
|
+
tapioca (0.13.3)
|
120
120
|
bundler (>= 2.2.25)
|
121
121
|
netrc (>= 0.11.0)
|
122
122
|
parallel (>= 1.21.0)
|
data/docs/getting_started.md
CHANGED
@@ -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
|
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
|
-
|
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
|
-
|
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(
|
19
|
+
def current_session_id(shopify_id_token, cookies, online)
|
20
20
|
if Context.embedded?
|
21
|
-
if
|
22
|
-
|
23
|
-
|
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}"
|
data/lib/shopify_api/version.rb
CHANGED
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.
|
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-
|
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.
|
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
|