simov / grant

OAuth Proxy
MIT License
4.08k stars 257 forks source link

iFrame redirect issue with Shopify oAuth #281

Closed matthewhilton closed 2 years ago

matthewhilton commented 2 years ago

I have setup grant with my Shopify embedded app using Nextjs API routes. So far the app installs fine and goes through the oAuth process as expected.

However, if I change my scopes from the ones originally installed what I would expect is to be taken back to the oAuth process to update the scopes. However, it seems as though the redirect from grant seems to be blocked by iframe security (shopify embedded apps are loaded in iframes)

The general problem is this:

  1. Install app normally
  2. Change the scopes
  3. In shopify dashboard, click on app to load it
  4. Shopify opens the app in an iframe and calls the app url to load it
  5. Grant detects that the scope has changed and attempts to redirect to the oauth screen
  6. (on Firefox 103.0.2) The embedded app iframe shows To protect your security, <shopify store url> will not allow Firefox to display the page if another site has embedded it. To see this page, you need to open it in a new window.

You can then click on 'Open site in new window' and it opens the oAuth screen as expected, however, this is not ideal for customers for obvious reasons.

The url it is trying to show/redirect to is https://<shopifystore>.myshopify.com/admin/oauth/request_grant?access_change_uuid=<uuid>&client_id=<clientid>

I was able to set this up to work in the past just by using NextJS request.redirect(<oauthurl>) - so I know its possible.

My guess is that somewhere in grant it is trying to send the URL instead of redirect - is there a setting that can change this? Its totally possible this might be an issue on Shopify's side, although I don't think so.

simov commented 2 years ago

If Shopify blocks the login form from being loaded inside an iframe then that's a setting on their end. Another way to do this is by loading up a new window with small size at the center of the screen, this is how PayPal are doing it for example. Once the OAuth flow is complete in that little window, it gets closed and the main page continues.

matthewhilton commented 2 years ago

What I find strange is my old implementation would simply call: response.redirect(https://${shop}/admin/oauth/authorize?client_id=${process.env.SHOPIFY_API_PUBLIC_KEY}&scope=${process.env.SHOPIFY_AUTH_SCOPES}&redirect_uri=${process.env.SHOPIFY_AUTH_CALLBACK_URL}&state=${nonce})

Which seemed to work fine - is grant doing it in a different way? I noticed I get a lot of API resolved without sending a response for /connect/shopify?... warnings which could be related

simov commented 2 years ago

Honestly it's a bit hard for me to tell what your setup exactly is, what it was before and so on. It might be helpful to clearly outline what was your initial setup that worked, what is your current setup, at least your Grant configuration, then how that iframe fits into all else and so on.

matthewhilton commented 2 years ago

Thanks for the quick replies @simov really appreciated.

I dug into this a bit more and in the end found that grant abstracted a bit too much for shopify's case. I tried my old code again and it actually doesn't work anymore so I suspect something changed on shopify's end (not surprised). The issue I don't think lies with grant but more just Shopify's very particular way of authenticating.

If anyone else comes across this issue in the future:

The solution is after the initial install, the oAuth redirect MUST be called from the client (e.g. React) and NOT the vercel api routes. You then need to (on the client inside the iframe) determine are you embedded or not, and if embedded use the shopify app bridge to dispatch a remote redirect else just do normal js redirect.