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
EnsureBilling and EnsureAuthenticatedLinks works with token exchange #1833
Conversation
25026be
to
4efdfb2
Compare
4efdfb2
to
841857f
Compare
@@ -45,8 +45,16 @@ def billing_required? | |||
end | |||
|
|||
def handle_billing_error(error) | |||
logger.info("#{error.message}: #{error.errors}") | |||
redirect_to_login |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was causing an infinite redirect loop in auth code flow because the shop
param gets added to the login path, and CallbackController
would re-check billing on auto login with the shop
param..
Changing the logic to redirect to login page without shop
param.
end | ||
|
||
def add_top_level_redirection_headers(url: nil, ignore_response_code: false) | ||
def add_top_level_redirection_headers(ignore_response_code: false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
url
argument is not used anywhere anymore, removing this.
Extracted helper RedirectForEmbedded.add_app_bridge_redirect_url_header(url, response)
to be reused elsewhere
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is something apps can use, right? Otherwise we might be removing functionality they need.
Although I guess in that case they could just use the other concern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmmm yea, although this method added more checks around when to add the headers. I think I'll just add the existing behaviour back to avoid breaking behaviour for apps
def jwt_expire_at | ||
expire_at = request.env["jwt.expire_at"] | ||
return unless expire_at | ||
|
||
expire_at - 5.seconds # 5s gap to start fetching new token in advance | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extracted these 'jwt' helpers to be inside WithShopifyIdToken
concern for reusability
def jwt_shopify_domain | ||
request.env["jwt.shopify_domain"] | ||
end | ||
|
||
def jwt_shopify_user_id | ||
request.env["jwt.shopify_user_id"] | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extracted these 'jwt' helpers to be inside WithShopifyIdToken
concern for reusability
7eddd95
to
bdf4b23
Compare
end | ||
|
||
def add_top_level_redirection_headers(url: nil, ignore_response_code: false) | ||
def add_top_level_redirection_headers(ignore_response_code: false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is something apps can use, right? Otherwise we might be removing functionality they need.
Although I guess in that case they could just use the other concern.
!params[:embedded].present? || params[:embedded] != "1" | ||
end | ||
|
||
def redirect_to_embed_app |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just out of curiosity - won't we have other places in the code that need to do this as well? Seems to me like this might also be extractable if that's the case.
host = if params[:host] | ||
params[:host] | ||
elsif params[:shop] | ||
Base64.encode64("#{sanitized_shop_name}/admin") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a little bit of an assumption - I think there are some cases where we might not want this (requests aren't coming from the admin), but we can deal with those if / when they happen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not quite sure if I understand? If they're using the EnsureHasSession
concern, they want to validate requests that are coming from the admin right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are cases where host
isn't necessarily shop/admin
, so we're basically assuming that will be the case whenever we hit this path. Which I think should be fine and in the unlikely event that this fails on any specific interaction, we can look into it later.
end | ||
|
||
test "#jwt_expire_at returns jwt.expire_at - 5 seconds from request env" do | ||
expected_expire_at = Time.now.to_i |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we locking down the time here? I wonder if this could lead to flaky tests if the second happens to shift during the run.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing blocking.
What this PR does
Before - Billing API error sent app into infinite redirect loop
infinite-loop-billing-error.mp4
After - Billing API error does not send app into infinite redirect loop
redirect-to-login.mp4
Token exchange works with EnsureBIlling and can load app after confirming charge
token-exchange-confirm-charge.mp4
Checklist
Before submitting the PR, please consider if any of the following are needed:
CHANGELOG.md
if the changes would impact usersREADME.md
, if appropriate./docs
, if necessary