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

When Shopify Online Session is lost the Authenticate process in Strapi fails #5

Closed
capsloq opened this issue Nov 3, 2022 · 9 comments
Assignees

Comments

@capsloq
Copy link

capsloq commented Nov 3, 2022

For some reason the online session gets deleted from time to time.
Basically a database entry in table session gets deleted. I am not sure why that happens, if its triggered by shopify or the plugin.
However, whenever it does happen the plugin fails to authenticate inside of /strategies/shopify-auth.js. It simply fails to load a session (since the db entry is missing). As a result most routes return a 401 since the strapi authentication failed. I am unsure if the plugin should be able to deal with such situations or why they occur.

If you have some insight please elaborate.

My only solution to this is to reinstall the app to recreate the session entry. By doing so everything goes back to fuctioning normally.

@j4m3sb0mb
Copy link
Contributor

Which version of the plugin are you using?
How many sessions do you have after the installation? (there should be two)

When you install the Shopify store the session created by installation is an offline session, then the user is redirected to the authentication and a online session is created. This is because an application may need both an offline access token for server usage and an online access token for user authenticated requests.
The installation endpoint is /api/shopify/install and its callback is /api/shopify/install/callback while the authenitcation endpoint is /api/shopify/auth and its callback is /api/shopify/auth/callback.
Both of this endpoints should not be used directly, the only one that should be used is the entry point endpoint which is /api/shopify which is responsible for redirecting requests to install or authentication or the app endpoint (SHOPIFY_REDIRECT_URL).

@j4m3sb0mb j4m3sb0mb self-assigned this Nov 5, 2022
@capsloq
Copy link
Author

capsloq commented Nov 5, 2022

Thanks for your answer.
Yes i know there should be 2 sessions (one online, one offline session)
I did get everything setup and anything does work correctly.

There are just some instances like every day or so that the ONLINE session gets deleted from the database.
I don't know why it gets deleted, might be a hook from the Shopify side because the online session is no longer valid or somth.? But i am just guessing.

However whenever this happens, (you can replicate this by simply deleting the online session in the database), the /api/shopify entry route fails to recreate the session and therefore authentication (and e.g Shopify.loadCurrentSession) is no longer working.

@j4m3sb0mb
Copy link
Contributor

j4m3sb0mb commented Nov 5, 2022

There are 3 reasons why the plugin deletes the current session and redirects with a 401:

  • when the request uses another shop in query string: here
  • when the scope has changed: here
  • when the session expires: here

When the redirect happens, if comes from a text/html request it should automatically redirect to the correct endpoint (install/auth), if comes from a normal GET request it should be handled by the frontend:

  • this response header tells if the app should do a redirect: X-Shopify-API-Request-Failure-Reauthorize
  • this response header tells where the app should redirect: X-Shopify-API-Request-Failure-Reauthorize-Url

This is a sample code I use to check if the shop is authenticated and if I shoud do a redirect:

const shop = await fetch('/api/shopify/shop').then(res => {
  if (res.status === 401) {
    const reauthHeader = 'X-Shopify-API-Request-Failure-Reauthorize';
    const reauthUrlHeader = 'X-Shopify-API-Request-Failure-Reauthorize-Url';
    const reauth = res.headers.get(reauthHeader);
    const reauthUrl = res.headers.get(reauthUrlHeader);
    if (reauth && reauthUrl) {
      window.location.href = reauthUrl;
    }
  }
  if (res.status >= 400) return;
  return res.json();
})

@j4m3sb0mb
Copy link
Contributor

The session probably expires and you should authenticate again

@capsloq
Copy link
Author

capsloq commented Nov 5, 2022

Okay thank your for the reasons of why a session gets deleted.
So lets say a session did get deleted shouldn't the entry route be able to reroute the user to reauth?
The code snippet you just posted proposes exactly that. (thank you for that)
But that's not in the plugin (yet), is it? No trying to complain just trying to figure out if i am using a old version or misconfigured something

@capsloq
Copy link
Author

capsloq commented Nov 5, 2022

Or is the code snippet you posted client side?

@j4m3sb0mb
Copy link
Contributor

j4m3sb0mb commented Nov 5, 2022

Yes this code should be on the client side, I use it when the app starts to check if the shop is still authenticated or if it should authenticate again or if the scopes are changed and the shop should be installed again.

This code was taken from @shopify/koa-shopify-auth but I can't tell you where exactly.

That said, I've never tested if instead of returning the headers the app can redirect directly on a GET/POST request made with fetch on the client side so I left the code there and I use it like I showed you.

@j4m3sb0mb
Copy link
Contributor

j4m3sb0mb commented Nov 6, 2022

So lets say a session did get deleted shouldn't the entry route be able to reroute the user to reauth?

You're probably right, it doesn't but it should

@capsloq
Copy link
Author

capsloq commented Nov 6, 2022

Understood. Thank you. I was so invested in the backend that i didn't see the obvious.
I kind of made it work within the backend. I basically checked if the shop is in the database while the online session is not and redirect to auth just before this line . But i didn't like that too much its probably not the best place to check for stuff like that.

I like your client side solution better.
But it might be some feature for the backend in the future.
Thank you so much for your time and help

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

No branches or pull requests

2 participants