Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch JwtPayload in order to correctly parse Checkout UI extensions session tokens #1346

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

linucs
Copy link

@linucs linucs commented Nov 3, 2024

Checkout UI session tokens are actually missing "iss" and "sid" keys (see: https://shopify.dev/docs/api/checkout-ui-extensions/2024-10/apis/session-token). The current implementation makes them mandatory, generating exceptions while verifying JWT tokens (see the new ShopifyApp::WithShopifyIdToken concern, and the legacy ShopifyApp::JWTMiddleware middleware).

Description

The PR is for:

  • Solving exceptions raised in the ShopifyAPI::Auth::JwtPayload constructor (line 30) when the JWT Token is missing the "iss" and "sid" keys (both optional in Checkout UI session tokens)
  • Any Checkout UI extension making authenticated API calls to an endpoint developed using the ShopifyApp engine fails, raising an obscure exception
  • PR impact: make "iss" and "sid" keys optional, and extract the correct shopify_user_id from the "sid" key, even when it's formatted as gid://shopify/Customer/<customerId>

How has this been tested?

Develop a basic frontend Checkout UI extension and make cors authenticated calls to a Rails backend developed using shopify_app gem (v22.4). Any request fails without reaching the corresponding controller, since an exception is raised in the ShopifyApp::JWTMiddleware middleware injected by the ShopifyApp engine (see engine.rb, row 20).
After applying the patch, requests are nomally executed without raising any exception.

Checklist:

  • My commit message follow the pattern described in here
  • I have performed a self-review of my own code.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have updated the project documentation.
  • I have added a changelog line.

@linucs linucs requested a review from a team as a code owner November 3, 2024 14:02
@linucs
Copy link
Author

linucs commented Nov 3, 2024

I have signed the CLA!

Copy link
Contributor

@lizkenyon lizkenyon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contribution good find that these tokens are inconsistent.

Could you add a test case to jwt_payload_test.rb to prevent regressions.

Could you also add to the CHANGELOG.md

@@ -27,15 +27,15 @@ def initialize(token)
decode_token(token, T.must(Context.old_api_secret_key))
end

@iss = T.let(payload_hash["iss"], String)
@iss = T.let(payload_hash["iss"], T.nilable(String))
@dest = T.let(payload_hash["dest"], String)
@aud = T.let(payload_hash["aud"], String)
@sub = T.let(payload_hash["sub"], String)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my testing I found that the sub claim could also be nil, if the customer is not logged in.

@@ -49,7 +49,7 @@ def shop

sig { returns(Integer) }
def shopify_user_id
@sub.to_i
@sub.tr("^0-9", "").to_i
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why you are extracting the ID?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants