Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Note: For changes to the API, see https://shopify.dev/changelog?filter=api
## Unreleased

- [#1481](https://github.com/Shopify/shopify-api-ruby/pull/1481) `ShopifyAPI::Auth::TokenExchange.exchange_token` now raises `ShopifyAPI::Errors::InvalidJwtTokenError` when token exchange rejects the session token with `invalid_identity_session`, matching the existing `invalid_subject_token` handling.
- [#1475](https://github.com/Shopify/shopify-api-ruby/pull/1475) Add an optional `client_assertion:` argument to `ShopifyAPI::Auth::ClientCredentials.client_credentials`. When supplied, the token request authenticates with a JWT client assertion and sends no client secret. Omitting it, or passing `nil`, keeps the existing client-secret behavior. See the [OAuth documentation](docs/usage/oauth.md#client-assertion-authentication).
- [#1475](https://github.com/Shopify/shopify-api-ruby/pull/1475) Add `ShopifyAPI::Auth::ClientAssertion.create`, an optional helper that signs a client assertion with an `RS256` (RSA, 2048-bit minimum) or `ES256` (EC P-256) private key your app owns. `client_id` defaults to `ShopifyAPI::Context.api_key`, the only value the helper reads from the context, and it never generates, imports, stores, or rotates keys.
- [#1475](https://github.com/Shopify/shopify-api-ruby/pull/1475) Add `ShopifyAPI::Errors::InvalidClientAssertionError`, raised for a blank or non-`String` assertion, for an assertion with surrounding whitespace, and for invalid signer input.
Expand Down
3 changes: 2 additions & 1 deletion lib/shopify_api/auth/token_exchange.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ def exchange_token(session_token:, requested_token_type:, shop: nil)
),
)
rescue ShopifyAPI::Errors::HttpResponseError => error
if error.code == 400 && error.response.body["error"] == "invalid_subject_token"
if error.code == 400 &&
["invalid_subject_token", "invalid_identity_session"].include?(error.response.body["error"])
raise ShopifyAPI::Errors::InvalidJwtTokenError, "Session token was rejected by token exchange"
end

Expand Down
18 changes: 18 additions & 0 deletions test/auth/token_exchange_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,24 @@ def test_exchange_token_rejected_session_token
end
end

def test_exchange_token_rejected_identity_session
modify_context(is_embedded: true)
stub_request(:post, "https://#{@shop}/admin/oauth/access_token")
.with(body: @non_expiring_offline_token_exchange_request)
.to_return(
status: 400,
body: { error: "invalid_identity_session" }.to_json,
headers: { content_type: "application/json" },
)

assert_raises(ShopifyAPI::Errors::InvalidJwtTokenError) do
ShopifyAPI::Auth::TokenExchange.exchange_token(
session_token: @session_token,
requested_token_type: ShopifyAPI::Auth::TokenExchange::RequestedTokenType::OFFLINE_ACCESS_TOKEN,
)
end
end

def test_exchange_token_deprecates_shop_argument
modify_context(is_embedded: true, expiring_offline_access_tokens: false)
ShopifyAPI::Logger.expects(:deprecated).with(
Expand Down
Loading