Shopify / shopify_app

A Rails Engine for building Shopify Apps
MIT License
1.77k stars 687 forks source link

Infinite redirect between /login, Home#index, and /granted_storage_access #1053

Closed yogodoshi closed 1 year ago

yogodoshi commented 4 years ago

I'm creating a new app and ran into this issue after installing the app in my test store, didn't customize any Shopify related code.

The infinite loop starts when I click the app on the store's list of installed apps.

Versions:

Rails server logs that shows the infinite loop:

Started GET "/?hmac=0f82d72949292546c12c4a9c173c8099d04f47f53897ad78b8b60a9d05fba9ff&locale=en&session=f64b9b51cb8fd00bd412d4e5dd4db4b0ec6108e077f5bc8ce824bd00d113f1c1&shop=storeurl.myshopify.com&timestamp=1598059348" for 2804:14c:8782:9312:6538:5840:a987:d051 at 2020-08-21 22:22:29 -0300
Processing by HomeController#index as HTML
  Parameters: {"hmac"=>"0f82d72949292546c12c4a9c173c8099d04f47f53897ad78b8b60a9d05fba9ff", "locale"=>"en", "session"=>"f64b9b51cb8fd00bd412d4e5dd4db4b0ec6108e077f5bc8ce824bd00d113f1c1", "shop"=>"storeurl.myshopify.com", "timestamp"=>"1598059348"}
Redirected to http://abc.sa.ngrok.io/login?return_to=%2F%3Fhmac%3D0f82d72949292546c12c4a9c173c8099d04f47f53897ad78b8b60a9d05fba9ff%26locale%3Den%26session%3Df64b9b51cb8fd00bd412d4e5dd4db4b0ec6108e077f5bc8ce824bd00d113f1c1%26shop%3Dstoreurl.myshopify.com%26timestamp%3D1598059348&shop=storeurl.myshopify.com
Completed 302 Found in 43ms (ActiveRecord: 0.0ms | Allocations: 7089)

Started GET "/login?return_to=%2F%3Fhmac%3D0f82d72949292546c12c4a9c173c8099d04f47f53897ad78b8b60a9d05fba9ff%26locale%3Den%26session%3Df64b9b51cb8fd00bd412d4e5dd4db4b0ec6108e077f5bc8ce824bd00d113f1c1%26shop%3Dstoreurl.myshopify.com%26timestamp%3D1598059348&shop=storeurl.myshopify.com" for 2804:14c:8782:9312:6538:5840:a987:d051 at 2020-08-21 22:22:29 -0300
Processing by ShopifyApp::SessionsController#new as HTML
  Parameters: {"return_to"=>"/?hmac=0f82d72949292546c12c4a9c173c8099d04f47f53897ad78b8b60a9d05fba9ff&locale=en&session=f64b9b51cb8fd00bd412d4e5dd4db4b0ec6108e077f5bc8ce824bd00d113f1c1&shop=storeurl.myshopify.com&timestamp=1598059348", "shop"=>"storeurl.myshopify.com"}
  Rendering /Users/cayomedeiros/.rvm/gems/ruby-2.6.5@store-reviewer/gems/shopify_app-14.1.0/app/views/shopify_app/sessions/request_storage_access.html.erb
  Rendered /Users/cayomedeiros/.rvm/gems/ruby-2.6.5@store-reviewer/gems/shopify_app-14.1.0/app/views/shopify_app/partials/_layout_styles.html.erb (Duration: 0.6ms | Allocations: 248)
  Rendered /Users/cayomedeiros/.rvm/gems/ruby-2.6.5@store-reviewer/gems/shopify_app-14.1.0/app/views/shopify_app/partials/_typography_styles.html.erb (Duration: 0.3ms | Allocations: 114)
  Rendered /Users/cayomedeiros/.rvm/gems/ruby-2.6.5@store-reviewer/gems/shopify_app-14.1.0/app/views/shopify_app/partials/_card_styles.html.erb (Duration: 0.2ms | Allocations: 113)
  Rendered /Users/cayomedeiros/.rvm/gems/ruby-2.6.5@store-reviewer/gems/shopify_app-14.1.0/app/views/shopify_app/partials/_button_styles.html.erb (Duration: 0.4ms | Allocations: 184)
  Rendered /Users/cayomedeiros/.rvm/gems/ruby-2.6.5@store-reviewer/gems/shopify_app-14.1.0/app/views/shopify_app/sessions/request_storage_access.html.erb (Duration: 39.4ms | Allocations: 12755)
Completed 200 OK in 45ms (Views: 44.2ms | ActiveRecord: 0.0ms | Allocations: 14612)

Started GET "/granted_storage_access?return_to=%2F%3Fhmac%3D0f82d72949292546c12c4a9c173c8099d04f47f53897ad78b8b60a9d05fba9ff%26locale%3Den%26session%3Df64b9b51cb8fd00bd412d4e5dd4db4b0ec6108e077f5bc8ce824bd00d113f1c1%26shop%3Dstoreurl.myshopify.com%26timestamp%3D1598059348&shop=storeurl.myshopify.com" for 2804:14c:8782:9312:6538:5840:a987:d051 at 2020-08-21 22:22:29 -0300
Processing by ShopifyApp::SessionsController#granted_storage_access as HTML
  Parameters: {"return_to"=>"/?hmac=0f82d72949292546c12c4a9c173c8099d04f47f53897ad78b8b60a9d05fba9ff&locale=en&session=f64b9b51cb8fd00bd412d4e5dd4db4b0ec6108e077f5bc8ce824bd00d113f1c1&shop=storeurl.myshopify.com&timestamp=1598059348", "shop"=>"storeurl.myshopify.com"}
Redirected to http://abc.sa.ngrok.io/?hmac=0f82d72949292546c12c4a9c173c8099d04f47f53897ad78b8b60a9d05fba9ff&locale=en&session=f64b9b51cb8fd00bd412d4e5dd4db4b0ec6108e077f5bc8ce824bd00d113f1c1&shop=storeurl.myshopify.com&timestamp=1598059348
Completed 302 Found in 1ms (ActiveRecord: 0.0ms | Allocations: 399)

Started GET "/?hmac=0f82d72949292546c12c4a9c173c8099d04f47f53897ad78b8b60a9d05fba9ff&locale=en&session=f64b9b51cb8fd00bd412d4e5dd4db4b0ec6108e077f5bc8ce824bd00d113f1c1&shop=storeurl.myshopify.com&timestamp=1598059348" for 2804:14c:8782:9312:6538:5840:a987:d051 at 2020-08-21 22:22:29 -0300
Processing by HomeController#index as HTML
  Parameters: {"hmac"=>"0f82d72949292546c12c4a9c173c8099d04f47f53897ad78b8b60a9d05fba9ff", "locale"=>"en", "session"=>"f64b9b51cb8fd00bd412d4e5dd4db4b0ec6108e077f5bc8ce824bd00d113f1c1", "shop"=>"storeurl.myshopify.com", "timestamp"=>"1598059348"}
Redirected to http://abc.sa.ngrok.io/login?return_to=%2F%3Fhmac%3D0f82d72949292546c12c4a9c173c8099d04f47f53897ad78b8b60a9d05fba9ff%26locale%3Den%26session%3Df64b9b51cb8fd00bd412d4e5dd4db4b0ec6108e077f5bc8ce824bd00d113f1c1%26shop%3Dstoreurl.myshopify.com%26timestamp%3D1598059348&shop=storeurl.myshopify.com
Completed 302 Found in 2ms (ActiveRecord: 0.0ms | Allocations: 576)

Started GET "/login?return_to=%2F%3Fhmac%3D0f82d72949292546c12c4a9c173c8099d04f47f53897ad78b8b60a9d05fba9ff%26locale%3Den%26session%3Df64b9b51cb8fd00bd412d4e5dd4db4b0ec6108e077f5bc8ce824bd00d113f1c1%26shop%3Dstoreurl.myshopify.com%26timestamp%3D1598059348&shop=storeurl.myshopify.com" for 2804:14c:8782:9312:6538:5840:a987:d051 at 2020-08-21 22:22:29 -0300
Processing by ShopifyApp::SessionsController#new as HTML
  Parameters: {"return_to"=>"/?hmac=0f82d72949292546c12c4a9c173c8099d04f47f53897ad78b8b60a9d05fba9ff&locale=en&session=f64b9b51cb8fd00bd412d4e5dd4db4b0ec6108e077f5bc8ce824bd00d113f1c1&shop=storeurl.myshopify.com&timestamp=1598059348", "shop"=>"storeurl.myshopify.com"}
  Rendering /Users/cayomedeiros/.rvm/gems/ruby-2.6.5@store-reviewer/gems/shopify_app-14.1.0/app/views/shopify_app/sessions/request_storage_access.html.erb
  Rendered /Users/cayomedeiros/.rvm/gems/ruby-2.6.5@store-reviewer/gems/shopify_app-14.1.0/app/views/shopify_app/partials/_layout_styles.html.erb (Duration: 0.0ms | Allocations: 6)
  Rendered /Users/cayomedeiros/.rvm/gems/ruby-2.6.5@store-reviewer/gems/shopify_app-14.1.0/app/views/shopify_app/partials/_typography_styles.html.erb (Duration: 0.0ms | Allocations: 5)
  Rendered /Users/cayomedeiros/.rvm/gems/ruby-2.6.5@store-reviewer/gems/shopify_app-14.1.0/app/views/shopify_app/partials/_card_styles.html.erb (Duration: 0.0ms | Allocations: 5)
  Rendered /Users/cayomedeiros/.rvm/gems/ruby-2.6.5@store-reviewer/gems/shopify_app-14.1.0/app/views/shopify_app/partials/_button_styles.html.erb (Duration: 0.0ms | Allocations: 5)
  Rendered /Users/cayomedeiros/.rvm/gems/ruby-2.6.5@store-reviewer/gems/shopify_app-14.1.0/app/views/shopify_app/sessions/request_storage_access.html.erb (Duration: 5.7ms | Allocations: 2300)
Completed 200 OK in 9ms (Views: 6.1ms | ActiveRecord: 0.0ms | Allocations: 3116)
asecondwill commented 3 years ago

Recreateable demo:

https://github.com/asecondwill/shopifydemo3

I'd really appreciate some help here please.

asecondwill commented 3 years ago

I added a branch to test if the problem was being in namespace directory. it hasnt helped.

https://github.com/asecondwill/shopifydemo3/tree/appinroot

marisveide commented 3 years ago

Hi!

We have this same issue, and we found that this is because the shopify_app gem "remembers" the return_to URL in session[:return_to]. So you can reproduce it by opening any controller of your app, and then install the app - you will see that it will infinitely redirect you to the same last manually opened controller URL.

So, if you once have sent the user to the /grant_storage_access path, then it will forever remember that in the session[:return_to]. The only way to get rid of it is to stop the app, delete the app session cookie in the browser, and then it will work again. Until the next time you will open some other link.

Ideally if the shopify_app gem cleared out that session value after redirecting, to avoid going into the infnite loop, which is now happening.

asecondwill commented 3 years ago

hi. thanks for helping.

It isnt redirecting to granted_storage_access. Maybe this is a slightly different issue.

mrpunkin commented 3 years ago

Any progress on this? I seem to be having the same issue and can't for the life of me get past this auth situation in Rails 6.1.4.1 with shopify_app 18.0.2.

fluke commented 3 years ago

I've tried a lot of the other solutions but I am like @mrpunkin completely stuck. I turned of JWT authentication and turned on cookie authentication and that was working but it doesn't work when installing the app from app store or test on development store and we were rejected from Shopify so I switched to JWT but now it is getting into an infinite loop.

Hey @onahkenneth, can you please confirm whether your app's home_controller.rb inherits from AuthenticatedController or ApplicationController? If it is authenticated, you'll want to replace it with the unauthenticated version to stop the infinite loop.

I need the home index to be authenticated so that I can show details. Not sure why this is leading to an infinite loop. I can see that it redirects back to /?hmac&shop&timestamp which seems to retrigger the login flow. Is it possible to change this return_to / redirect_url value not the root or somehow not retrigger the login flow.

My app is currently: embedded_app is false allow_jwt_authentication is true allow_cookie_authentication is false

fluke commented 3 years ago

There does seem to be some code that is meant to stop the return_to:

https://github.com/Shopify/shopify_app/blob/master/lib/shopify_app/controller_concerns/login_protection.rb#L173

It seems like it won't redirect back if it has just the hmac, shop and timestamp params but I'm still ending up with a redirect like this /login?return_to=%2F%3Fhmac%3Db947a931fb272cb88dc0224d347252ff4a046497cbe8f67d16a7cfd2f047cee7%26host%3Dc2hvcnR5LXNob3J0LXNob3J0cy5teXNob3BpZnkuY29tL2FkbWlu%26shop%3Dshorty-short-shorts.myshopify.com%26timestamp%3D1635485446&shop=shorty-short-shorts.myshopify.com. The shop param is actually set twice so it seems like there might be an issue with URL encoding.

fluke commented 3 years ago

I tried setting the index page to an unauthenticated page but the moment you move from there to an authenticated page it triggers the login again and you're sent straight back to the index page so there seems to be an issue with the login with JWT.

Will revert to using cookie authentication. It was working better and I'll manually trigger login.

mrpunkin commented 3 years ago

@fluke Unfortunately after doing a bunch more work on converting my app it seems that there is a lot of work to be done for apps that use server side rendering. I found this article tucked under the Session Token info in their dev pages: https://shopify.dev/apps/auth/session-tokens/server-side-rendered-apps and I found this info about a mixin to ensure authenticated links: https://github.com/Shopify/shopify_app/blob/2c608f06cb2e74840613aa3b6da935038bf19463/docs/shopify_app/authentication.md#shopifyappensureauthenticatedlinks

I unfortunately haven't gotten very far yet otherwise I may be able to help more. The gist of it though is that you now have to support a splash page that handles the AppBridge iFrame embedding, then from there take your user off to an authenticated page but that link to that page needs to include the Session Token or be rendered in JS as a single-page app.

kirillplatonov commented 3 years ago

Here's ready to use sample of Shopify app with JWT and Hotwire integration: https://github.com/kirillplatonov/shopify-hotwire-sample

fluke commented 3 years ago

I was able to solve the original issue that we faced with cookie authentication which was a user uninstalls the app and then tries to reinstall while the cookie is still valid as per our app. I had to invalidate the current session and things work fine. The simplest way to do that is to make an API call. It will fail if the app was uninstalled and LoginProtection handles the Unauthorised error by clearing the session. I think there may be better ways by handling the app uninstalled event or some such but this is what I've done for now.

devender-nexasky commented 2 years ago

for non-embedded apps in shopify_app.rb config.allow_cookie_authentication = true , fixes this for me

github-actions[bot] commented 2 years ago

This issue is stale because it has been open for 90 days with no activity. It will be closed if no further action occurs in 14 days.

github-actions[bot] commented 1 year ago

We are closing this issue because it has been inactive for a few months. This probably means that it is not reproducible or it has been fixed in a newer version. If it’s an enhancement and hasn’t been taken on since it was submitted, then it seems other issues have taken priority.

If you still encounter this issue with the latest stable version, please reopen using the issue template. You can also contribute directly by submitting a pull request– see the CONTRIBUTING.md file for guidelines

Thank you!