Module: ShopifyAPI::Auth::TokenExchange

Extended by:
T::Sig
Defined in:
lib/shopify_api/auth/token_exchange.rb

Defined Under Namespace

Classes: RequestedTokenType

Constant Summary collapse

TOKEN_EXCHANGE_GRANT_TYPE =
"urn:ietf:params:oauth:grant-type:token-exchange"
ID_TOKEN_TYPE =
"urn:ietf:params:oauth:token-type:id_token"

Class Method Summary collapse

Class Method Details

.exchange_token(shop:, session_token:, requested_token_type:) ⇒ Object

Raises:



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/shopify_api/auth/token_exchange.rb', line 29

def exchange_token(shop:, session_token:, requested_token_type:)
  unless ShopifyAPI::Context.setup?
    raise ShopifyAPI::Errors::ContextNotSetupError,
      "ShopifyAPI::Context not setup, please call ShopifyAPI::Context.setup"
  end
  raise ShopifyAPI::Errors::UnsupportedOauthError,
    "Cannot perform OAuth Token Exchange for private apps." if ShopifyAPI::Context.private?
  raise ShopifyAPI::Errors::UnsupportedOauthError,
    "Cannot perform OAuth Token Exchange for non embedded apps." unless ShopifyAPI::Context.embedded?

  # Validate the session token content
  ShopifyAPI::Auth::JwtPayload.new(session_token)

  shop_session = ShopifyAPI::Auth::Session.new(shop: shop)
  body = {
    client_id: ShopifyAPI::Context.api_key,
    client_secret: ShopifyAPI::Context.api_secret_key,
    grant_type: TOKEN_EXCHANGE_GRANT_TYPE,
    subject_token: session_token,
    subject_token_type: ID_TOKEN_TYPE,
    requested_token_type: requested_token_type.serialize,
  }

  client = Clients::HttpClient.new(session: shop_session, base_path: "/admin/oauth")
  response = begin
    client.request(
      Clients::HttpRequest.new(
        http_method: :post,
        path: "access_token",
        body: body,
        body_type: "application/json",
      ),
    )
  rescue ShopifyAPI::Errors::HttpResponseError => error
    if error.code == 400 && error.response.body["error"] == "invalid_subject_token"
      raise ShopifyAPI::Errors::InvalidJwtTokenError, "Session token was rejected by token exchange"
    end

    raise error
  end

  session_params = T.cast(response.body, T::Hash[String, T.untyped]).to_h

  Session.from(
    shop: shop,
    access_token_response: Oauth::AccessTokenResponse.from_hash(session_params),
  )
end