Skip to content

Commit c689206

Browse files
committed
Add refresh token class
1 parent 5463b38 commit c689206

File tree

2 files changed

+149
-0
lines changed

2 files changed

+149
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# typed: strict
2+
# frozen_string_literal: true
3+
4+
module ShopifyAPI
5+
module Auth
6+
module RefreshToken
7+
extend T::Sig
8+
9+
class << self
10+
extend T::Sig
11+
12+
sig do
13+
params(
14+
shop: String,
15+
refresh_token: String,
16+
).returns(ShopifyAPI::Auth::Session)
17+
end
18+
def refresh_access_token(shop:, refresh_token:)
19+
unless ShopifyAPI::Context.setup?
20+
raise ShopifyAPI::Errors::ContextNotSetupError,
21+
"ShopifyAPI::Context not setup, please call ShopifyAPI::Context.setup"
22+
end
23+
24+
shop_session = ShopifyAPI::Auth::Session.new(shop:)
25+
body = {
26+
client_id: ShopifyAPI::Context.api_key,
27+
client_secret: ShopifyAPI::Context.api_secret_key,
28+
grant_type: "refresh_token",
29+
refresh_token:,
30+
}
31+
32+
client = Clients::HttpClient.new(session: shop_session, base_path: "/admin/oauth")
33+
response = begin
34+
client.request(
35+
Clients::HttpRequest.new(
36+
http_method: :post,
37+
path: "access_token",
38+
body:,
39+
body_type: "application/json",
40+
),
41+
)
42+
rescue ShopifyAPI::Errors::HttpResponseError => error
43+
ShopifyAPI::Context.logger.debug("Failed to refresh access token: #{error.message}")
44+
raise error
45+
end
46+
47+
session_params = T.cast(response.body, T::Hash[String, T.untyped]).to_h
48+
49+
Session.from(
50+
shop:,
51+
access_token_response: Oauth::AccessTokenResponse.from_hash(session_params),
52+
)
53+
end
54+
end
55+
end
56+
end
57+
end

test/auth/refresh_token_test.rb

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# typed: false
2+
# frozen_string_literal: true
3+
4+
require_relative "../test_helper"
5+
6+
module ShopifyAPITest
7+
module Auth
8+
class RefreshTokenTest < Test::Unit::TestCase
9+
def setup
10+
super()
11+
12+
@stubbed_time_now = Time.now
13+
@shop = "test-shop.myshopify.com"
14+
@refresh_token = "refresh_token_#{SecureRandom.alphanumeric(10)}"
15+
16+
@refresh_token_request = {
17+
client_id: ShopifyAPI::Context.api_key,
18+
client_secret: ShopifyAPI::Context.api_secret_key,
19+
grant_type: "refresh_token",
20+
refresh_token: @refresh_token,
21+
}
22+
23+
@refresh_token_response = {
24+
access_token: "access_token_#{SecureRandom.alphanumeric(10)}",
25+
expires_in: 1000,
26+
refresh_token: "refresh_token_#{SecureRandom.alphanumeric(10)}",
27+
refresh_token_expires_in: 3000,
28+
scope: "write_products,read_orders",
29+
}
30+
end
31+
32+
def test_refresh_access_token_success
33+
stub_request(:post, "https://#{@shop}/admin/oauth/access_token")
34+
.with(body: @refresh_token_request)
35+
.to_return(
36+
body: @refresh_token_response.to_json,
37+
headers: { "Content-Type" => "application/json" },
38+
)
39+
40+
expected_session = ShopifyAPI::Auth::Session.new(
41+
id: "offline_#{@shop}",
42+
shop: @shop,
43+
access_token: @refresh_token_response[:access_token],
44+
scope: @refresh_token_response[:scope],
45+
is_online: false,
46+
expires: @stubbed_time_now + @refresh_token_response[:expires_in].to_i,
47+
refresh_token: @refresh_token_response[:refresh_token],
48+
refresh_token_expires: @stubbed_time_now + @refresh_token_response[:refresh_token_expires_in].to_i,
49+
)
50+
51+
session = Time.stub(:now, @stubbed_time_now) do
52+
ShopifyAPI::Auth::RefreshToken.refresh_access_token(
53+
shop: @shop,
54+
refresh_token: @refresh_token,
55+
)
56+
end
57+
58+
assert_equal(expected_session, session)
59+
end
60+
61+
def test_refresh_access_token_context_not_setup
62+
modify_context(api_key: "", api_secret_key: "", host: "")
63+
64+
assert_raises(ShopifyAPI::Errors::ContextNotSetupError) do
65+
ShopifyAPI::Auth::RefreshToken.refresh_access_token(
66+
shop: @shop,
67+
refresh_token: @refresh_token,
68+
)
69+
end
70+
end
71+
72+
def test_refresh_access_token_unauthorized
73+
stub_request(:post, "https://#{@shop}/admin/oauth/access_token")
74+
.with(body: @refresh_token_request)
75+
.to_return(
76+
status: 401,
77+
body: { error: "unauthorized" }.to_json,
78+
headers: { "Content-Type" => "application/json" },
79+
)
80+
81+
ShopifyAPI::Context.logger.expects(:debug).with(regexp_matches(/Failed to refresh access token/))
82+
83+
assert_raises(ShopifyAPI::Errors::HttpResponseError) do
84+
ShopifyAPI::Auth::RefreshToken.refresh_access_token(
85+
shop: @shop,
86+
refresh_token: @refresh_token,
87+
)
88+
end
89+
end
90+
end
91+
end
92+
end

0 commit comments

Comments
 (0)