Have your say in Community Polls: What was/is your greatest motivation to start your own business?
Our Partner & Developer boards on the community are moving to a brand new home: the .dev community forums! While you can still access past discussions here, for all your future app and storefront building questions, head over to the new forums.

Introducing cookieless authentication beta with App Bridge

Introducing cookieless authentication beta with App Bridge

Liam
Community Manager
3108 344 889

With the strong focus on privacy, browsers have recently started phasing out support for the 3rd party cookie. This has caused issues for embedded apps which until now have required the use of 3rd party cookies.

Our new App Bridge auth beta introduces “session tokens” to empower developers to create faster, more flexible, and more compatible apps. Session token based auth does not depend on cookies and instead relies on a Shopify-generated token that your app needs to send with every request.

In order to get started with App Bridge auth, or migrate your current app from traditional, cookie-based authentication, you can follow the guide in our developer documentation.

Questions about App Bridge auth or session tokens? Post them in this board or reach out to support through your partner dashboard.

Liam | Developer Advocate @ Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit Shopify.dev or the Shopify Web Design and Development Blog

Replies 133 (133)

Adam_Hurlburt
Explorer
41 1 11

Will koa-shopify-auth package be updated to leverage this?

 

I see in the resources a sample ruby app was provided, would be nice to see some examples for some of the other supported languages (like react / node examples).

 

Michael_Ragalie
Shopify Staff
38 2 12

Thanks for the suggestion, Adam!

We're still figuring out the best way for us to surface the backend logic for node. The good news is that most of the logic lives in App Bridge, and you can use the `authenticatedFetch` fetch implementation with pretty much any modern JS framework (see more about `authenticatedFetch` here: https://shopify.dev/tools/app-bridge/authentication#setup).

I did notice that a community member created a helper to validate the session token for node: https://github.com/leighs-hammer/shopify-jwt-auth-verify You could see if that meets your needs.

To learn more visit the Shopify Help Center or the Community Blog.

Indinuity
Shopify Partner
41 1 2

Hi @Liam 

How does this relate to embedded Shopify POS authentication?

I am currently servicing an ongoing issue with many users of my Shopify POS embedded app on iPad's where our cookie based authentication is throwing users into an endless "accept-cookie" loop. ( testing on a tablet with iOS 12.8.4)

I noticed there is a new session parameter being passed into the requests as well.

Can you confirm there is no hope with the above version (iOS 12.8.4) ?

 

 

Reward yourself and your Customers.
HunkyBill
Shopify Partner
4853 60 568

Has anyone built an App with this pattern? I have gone through all the example code published so far and honestly, it looks nightmarish. I can understand from the high level that if you take a stripped down diagram of the world of request/response, you can use the JWT as a way to say this request is OK and this response is OK. Fine.

The example code of Shopify App with this pattern is a point to discuss. It shows off ever so slightly ways in which one one deploy this pattern. Thanks! Digging in though and it starts reveal serious change. For example, take the

module ShopifyApp
  class SessionsController < ActionController::Base
      include ShopifyApp::LoginProtection

Looking through this code. Wow. There are like 120 lines of code now so intermingled with cookies and validation and access and .... hard to follow how JWT helps.

So I read the pattern and it says:

- render something unauthenticated (because no cookies) once, with a placeholder and hopefully you'll get a token in there. Render some JS there too, to do stuff

- use JS and the token you received to ask your server for good stuff.

So fine but now I am in the world of strictly using a front-end like React, and ensuring my backend is rigged to deal with JWT. I am not seeing that pattern in Rails, but perhaps I am wrong. Is there a common open source Rails project that uses JWT to show off how Shopify is expecting us to use it? 

I love the idea and concept of getting away from third-party cookies as 100% of my service calls for an App are now Chrome does not work even though samesite cookies are set properly. But this JWT pattern does not look clean and easy from the perspective of shopify_app combined with shopify_api.

Maybe if there was a more robust demo it would be easier to grok. Something still weird too, is the oAuth flow, and how it is affected? First we need to install an App, what aspects of the current install are affected? JWT does nothing to help with install, so what about all those helper JS files to play with cookies? All done with?

Maybe it is time to fork this gem to one that is suited to React, JWT and go from there? In other words it is getting hard for me (a Rails loser) to follow the part of the gem that matter, and those that no longer matter, and then learning those that are spanky new...

Yelp? Help? Welp?

 

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
Michael_Ragalie
Shopify Staff
38 2 12

Thanks Dave, this is really good feedback. I think you've identified a few things we can do better:

Looking through this code. Wow. There are like 120 lines of code now so intermingled with cookies and validation and access and ....

I agree 100% with this. The new JWT code in `shopify_app` is actually pretty minimal. The existing cookie code, especially with the Safari workarounds, is a nightmare to parse, however.

We made a choice early on to support the cookie-based and JWT flows operating simultaneously in the app. In theory this would be useful for apps transitioning from the cookie-based flow to the JWT flow. In practice I think it's made the `shopify_app` code and process even harder to understand than it was before, and introduced the potential for weird edge cases.

I think we (the folks at Shopify working on this) should refactor the code in `shopify_app` and separate the two flows, so consumers can include a `ShopifyApp::CookieAuthenticated` module if they're using the cookie-based auth, but use a new `ShopifyApp::JWTAuthenticated` module if they're using JWT. That won't change the code that's needed in your app, but it will make it easier for folks digging into the `shopify_app` gem (such as yourself) to see what it's doing and will insulate the new, leaner code from the mess that is the cookie-based module. We're still in beta, so now's the time to make a change like that.

JWT does nothing to help with install, so what about all those helper JS files to play with cookies? All done with?

You're right that JWT doesn't fundamentally change the OAuth/install flow.

That being said, when we built the cookie workarounds for Safari a couple years ago, we shoehorned them into the OAuth flow. This was a short-term cheap, long-term expensive decision. With the JWT pattern we don't need any of those JS includes for the Safari workarounds, so we (the folks at Shopify working on this) should refactor so that we can use a much slimmed down OAuth/install flow with JWT and avoid including all that Safari workaround cruft unnecessarily.

> Maybe it is time to fork this gem to one that is suited to React, JWT and go from there?

A separate gem may make sense. At the very least we should commit to separating the flows better within the existing gem. If, after doing that, we all think it would be useful to move the JWT logic into a totally separate gem, I'm not opposed to that.

So fine but now I am in the world of strictly using a front-end like React, and ensuring my backend is rigged to deal with JWT. I am not seeing that pattern in Rails, but perhaps I am wrong.

Putting the JWT aspect aside for a second, I think it's pretty common these days to build the frontend using a JS framework and for the frontend to use an API provided by the backend to fetch the data needed to render the views. If the app is already architected in this "JS-rendered frontend, backend exposes API" pattern, then including the JWT is straightforward.

Recently we've been more forceful about recommending this pattern (you'll notice the most prominent guide on shopify.dev suggests using Node/React, for example). We realize, however, that lots of people have built apps that are server-rendered. It's not as turnkey to use it with these kind of apps, but it's definitely doable.

I think what we can do is what you suggest: build better tools/examples for the server-rendered use case, and the Rails rendered case in particular.

Thanks again for your feedback on this. Most of our focus (and our early beta testers) has been single-page apps that are easier to implement JWT for. One of the things we're hoping to learn as part of this public beta is what's missing for folks with server-rendered apps. This is a great start!

To learn more visit the Shopify Help Center or the Community Blog.

TwoColors
Shopify Partner
78 0 23

any chance JWT will be implemented into shopify-cli? currently when you build project with node.js + react, it still use cookies

Maciej Tokarczyk
rezaansyed
Shopify Staff
7 0 3

Hi @Indinuity!

Thanks for bringing this up with us. The POS channel team is aware of this and is working on converting over the app to the new authentication flow. Once that is out there, it should alleviate the issue users are seeing.

To learn more visit the Shopify Help Center or the Community Blog.

MathewsJoseph
Shopify Partner
7 0 4

Hey Michael! I have created a complete app using NodeJs, React, and MongoDB. You can check that out on:
https://github.com/MathewsJoseph25/create-shopify-app

andreiasdfg
Tourist
11 0 1

I've been asking 100 people on this forum for help, finally found your post. To give you some context, I have a shopify application, backend Koa (auth done with koa-shopify-auth), frontend React, currently I'm using cookies to set shopOrigin in order to configure the App Bridge Provider. On Safari is not working and on incognito (tested it), it works only on Firefox and Chrome. So, as far as I can see, this 'app-bridge-utils' is not ready, i can't find any documentation, I don't know how to implement it in my react app... So, ye, asking again on this forum, using koa and koa-shopify auth, how can I send the shopOrigin to the frontend to configure App Bridge, without cookies? 🙂 If you answer, I'm really happy to listen to your advice

Michael_Ragalie
Shopify Staff
38 2 12

Hi, good question!

Whenever Shopify loads your app in the embedded context, the app URL contains several URL parameters, including a `shop` parameter that is the shop origin. You can use this `shop` parameter to load up App Bridge.

Does that make sense?

To learn more visit the Shopify Help Center or the Community Blog.

andreiasdfg
Tourist
11 0 1

Yep, even tho it's a bit tricky. I've created a function in <head> in index.html to get that shop param, and i taught that it would work now without cookies but it seems like during the authorization (using koa-shopify-auth) at some point i need the shop param before i have that URL that contains state and shop. So i do something like this in my App.js where i wrap the providers, and it's working on all browsers and incognito EXCEPT SAFARI. lol i dont know what is going on in safari..

 

'Whenever Shopify loads your app in the embedded context, the app URL contains several URL parameters, including a `shop` parameter that is the shop origin. You can use this `shop` parameter to load up App Bridge.'

So at a certain point, App Bridge tries to get shop param but it happens before Shopify loads my app in embedded context, thats what im trying to say..

 

 

const config = {
    apiKey: process.env.REACT_APP_SHOPIFY_API_KEY,
    shopOrigin: window.getUrlParameter('shop') || Cookies.get('shopOrigin'),
    forceRedirect: true,
  }

 

 

andreiasdfg
Tourist
11 0 1

So if you have any idea why App Bridge requires the shopOrigin before i get that embedded URL link with shopOrigin, or why auth doesn't work on Safari let me know :d

prince_lyzer
Tourist
13 0 2

hello @Michael_Ragalie 

Yes, it will be working when app is loaded first time. but when I redirect to another page and then reload the iframe, at that time, shopify did not provides the shop or host key in the url. and Here issue arises.

 

app bridge throws an error of shop origin is required.

 

Please consider this case.

robbwinkle
Tourist
5 0 3

@prince_lyzer I had the same issue and the reason is that when you link to the new route you are not including the shop parameter.  So it's probably something like /about instead of /about?shop=myshop.myshopify.com.  The problem relies in your router not maintaining the parameter when changing routes.  

Possible solutions:

  1. It is possible in React to listen for link changes and append the current shop parameter to the new link but you will get a browser console error.  
  2. You could also append the shop parameter to every link programmatically, but this is hard to maintain. Each time you add a link you would need to make sure the parameter is added
  3. Use React Context to maintain the parameter
  4. If using Next.js, use server side props in next.js on each page to pass the shop from the parameter as a prop. This is difficult to maintain as well because essentially you copy/pasta it to every page.

I didn't like either of these solutions but at the time didn't have time to track down another solution. 

I used a combination of both 1 & 2 in case future developers forgot to add the parameter on new links. Some of the other more elegant solutions I tried didn't work so I went with the brute force approach given time constraints.

prince_lyzer
Tourist
13 0 2

I do the same solution for now.

kyle_truong
Shopify Partner
60 6 16

I'm having some issues with app-bridge 2.0.3, specifically the `forceRedirect` option. My embedded app loads the skeleton unauthenticated as suggested by the Session token tutorial, the skeleton loads app bridge and then app bridge redirects to a broken url at `https://<myshopifydomain>/apps/<shopifykey>`. Before, it redirected to `https://<myshopifydomain>/admin/apps/<shopifykey>` and that worked but it no longer seems the case. This affects the flow for creating app subscriptions after confirming the subscription and getting redirected back to the returnUrl, but also I've had issues with this during the app submission process. 

I created a GitHub issue at https://github.com/Shopify/shopify-app-bridge/issues/65 but haven't received a response yet. I'm not sure where to go from here or if I'm missing something really obvious. 

sonium
Shopify Partner
15 0 1

Is there the possibility to test an app with the shop_origin of a different merchant's shop (obviously one that has the app installed)?

This would be great for helping merchants to resolve issues with the app!

 

HunkyBill
Shopify Partner
4853 60 568

You always build and test with your own development store! That way you get to work with production and development API keys. That way you test and play with the cloud (your merchant customers) and using a decent tunnel like ngrok, localhost on your machine.

If you are having trouble with this concept, you can experiment and quickly get up to speed.

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
sonium
Shopify Partner
15 0 1

I didn't mean testing per-se.

Is there the possibility log into an app with the shop_origin of a different merchant's shop for helping the merchant to resolve issues with the app?

HunkyBill
Shopify Partner
4853 60 568

Not sure I understand you. Logging in as the merchant is what you want? You can only do that if you ask them for permission and they grant it to you. Your partner account has that built in.

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
bestelectric11
Visitor
2 0 0
I am currently servicing an ongoing problem with many customers of my Shopify POS embedded app on iPad's in which our cookie based totally authentication is throwing customers into an limitless "be given-cookie" loop. ( trying out on a pill with iOS Best Electric Smoker )
banned

dzdzteste
Visitor
1 0 0

what is haill

Bengk
Shopify Partner
21 0 13

I'd like to move over and ditch cookies.

What's the process for apps that are developed on Node using this configuration: https://shopify.dev/tutorials/build-a-shopify-app-with-node-and-react

Does this mean we get rid of koa-shopify-auth entirely? 

What replaces koa-shopify-auth for the initial authentication flow?

Haven't been able to find any outline on how developers should go about this.

Thanks

releod
Tourist
9 0 8

Hi @Liam / @Michael_Ragalie 

Can we get some updated docs, specifically around new users accessing an already installed application. I see there is another fetch method available `userAuthorizedFetch` - which possibly handles per user tokens?

Would love to get more clarity in the docs, this is likely the best way to get more folks moving off cookies and into session based.

 

Also any plans to expose current user / shop / device information from within App Bridge?

rezaansyed
Shopify Staff
7 0 3

Hi @releod,

`userAuthorizedFetch` is in reference to our new solution to updating online access tokens. We are still working on this and do not suggest using this yet. However, if you are authenticating requests between your app frontend and app backend, you can leverage the `userAuthenticatedFetch` fetch implementation. It is a custom fetch operation that will fetch the session token and append it in your request.

Here are the docs for the new auth using session tokens: https://shopify.dev/tools/app-bridge/authentication
Example using the the `userAuthenticatedFetch`: https://shopify.dev/tools/app-bridge/authentication#frontend-changes

To learn more visit the Shopify Help Center or the Community Blog.

Martin_Caum
Shopify Partner
40 3 22

Maybe I am missing something here, but I am currently working on an app right now and have hand coded the Oauth handshake without the use of cookies. My app is currently embedded and can handle things like pulling orders from the server and everything. All without using cookies. Am I missing a key part to writing a secure app or is this dependent on how the app works and what it wants to do? From my understanding, and what I have completed so far, the Oauth handshake is all done through a ping-pong volley of GET requests. Once this is done, I am able to get a permanent token. Any calls to the Shopify API are done using this token. I could maybe see once the token has already been received then one could argue that the original call for the Oauth could be sent from anywhere/anyone. But the next step is to ping Shopify's server with the response. This step should prevent allowing access to the app from an outside source.

I did add in an extra security measure where once the hmac/nonce is verified and I have gotten the response back from Shopify's server I generate a nonce/HMAC of my own and the HMAC is sent to the final redirect URL by way of URL parameter. Once the page of the app loads with the HMAC it verifies it (server side with PHP) against the nonce on my server (that never left the server) as well as checks against a very short timeout from when the nonce and HMAC are generated. If all of that checks out I know this session came from the Shopify admin and should be secure so I serve the front end of the app. During that session any calls that need to be made come from my app's front end to my server, where the server would make the calls to Shopify's API using the stored permanent token.

One could maybe argue that it is this call from the app's front-end to the server that could be vulnerable but even then I could, once the app has verified my nonce/HMAC, generate a session Id cookie (1st party, not 3rd party) to be sent with the call to the server to access the Shopify API. An even further step could be taken that each time that happens or a new page/state of my app's front end is loaded, a new session Id is generated. This is all a very drawn out process but I think it is simple enough to handle and should be more than secure enough without the use of third party cookies.

HunkyBill
Shopify Partner
4853 60 568

If your App is embedded in an iframe, note that the token exchange happens outside that iframe. So to get your session happening inside the iframe, requires a mechanism like cookies. Since that is now verboten with several browsers without approval, that is the issue at hand. If your App just lives on it's own, then sure, you can manage your own cookies and not experience this problem. Only if you're embedding your App is the transition to JWT a needed thing at this time. Since the exchange of a JWT can occur with just headers, it evades this third-part cookie issue.

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
Martin_Caum
Shopify Partner
40 3 22

But this is what I am not following. By "embedded app" you mean one that shows in an iframe inside the Shopify admin? Mine does this. It is loading and authenticating inside the iframe but I am not using cookies. Are there special features/functions of communication that are not done from server calls to the API? Or is this more about trying to avoid needing server side scripting?

HunkyBill
Shopify Partner
4853 60 568

You are not loading an authenticated session inside the iframe. Shopify is hoisting you into an iframe but it cannot hoist your session in there, without using cookies. Anyway, if you are happy and your App works, why worry. If you are actually leaking and not secure, someone will hack you and or inform you and you'll fix things up later. I am sure you are fine though. It is tough to screw up and get away with it.

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
releod
Tourist
9 0 8

I agree with HunkyBill here. It may also be worth hearing about how you've accomplished this.. worst case we can poke some security holes in your setup, best case we can learn something new.

Martin_Caum
Shopify Partner
40 3 22

Absolutely. If I have any concern it is that I am doing something insecure. But I think I have thought it all out pretty well. Feel free to pick it apart. I actually wanted to work in PHP for multiple reasons (main one being I tried getting started with the tutorials out there for Ruby with Shopify's gem and I ended up with a 96MB app that just authenticated (and barely did that even) before I even started coding out the actual functionality of the app). The only PHP app I found was outdated and did not work with Shopify's current Oauth and API, so I wrote my own bare-bones PHP app and put it on GitHub. It includes all steps to get it up and running easily as well as the added security measures I spoke about in my first comment on here. Check it out here and let me know what you think or if there are any flaws you find in it: https://github.com/XenithTech/php-shopify-app-skeleton

Martin_Caum
Shopify Partner
40 3 22

Also, I have not gone through and commented anything yet so feel free to ask me either on here or GitHub about what any of it is doing. But it should be mostly straightforward.

HunkyBill
Shopify Partner
4853 60 568

I agress on the bloat. I used Sinatra for years to avoid it. But you have to also remember this. That bloat buys you code battle-tested and proven, code you eventually need, and code you cannot hope to replicate yourself. Rare is the person that writes an App these days without some kind of framework. So while it is true you get little out of the box for your initial foray into Rails, for just a few extra minutes of work, you could put into play a useful API call pattern, that is battle-tested for the same 96MB. Good luck rolling your own there. Also PHP? Hardcore hanging on to yesteryear! It is still a thing for sure, but you won't stumble across anything nice for Shopify. Stick with Ruby, or Python (or even gasp, Node) for the most current community efforts. And don't discount the fact that Shopify's gems for App and API are always going to expose cutting edge before anything else by default. PHP will almost always be your long distant cousin on a dial-up modem with electricity only 4 hours a day, from a bicycle feeding a battery when the sun does not shine. 

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
Martin_Caum
Shopify Partner
40 3 22

I definitely get what you are saying about having the pre built out API but the Admin API for Shopify is very well documented and very straightforward as far as the calls being made. The wrapper API doesn't seem to give me much advantage overall. As I go and need to make calls I am going to be building on this PDP bare-bones app to have a similar built in API structure of reusable functions but I also gain a lot out of doing this by hand in way of learning. Now the choice of PHP is for a whole different discussion. I would argue (as an active professional web developer) though that PHP is actually by no means a dying language. The new versions of PHP have fixed a lot of old performance concerns and between just WordPress and Magento alone, there are thousands upon thousands of sites written in PHP that will likely never be rewritten to another language. That being said, I am familiar with Node and may give that a shot at some point. 

HunkyBill
Shopify Partner
4853 60 568

What is this wrapper API you speak of? I am not familiar with referring to anything as a wrapper API

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
Martin_Caum
Shopify Partner
40 3 22

@HunkyBill Wrapper API refers to an API that wraps around another one. In other words, a class/object that contains functions taking in arguments to make calls to the REST API and returns an object native to that language. Something like `$products = $Store->getProduct('29249471');`.

HunkyBill
Shopify Partner
4853 60 568

Thanks @Martin_Caum I get it!

Kind of a precocious thing to say though, as almost everyone in conversation just makes API calls. Hence why it can be a head-scratcher for a second. You did what?

If you used PHP, sure it looks different than Ruby or Javascript code would, because they are different languages with unique syntaxes. I guess the years have dulled my ability to just let it go. Of course ActiveResource is the common Ruby wrapper around making Rest API calls. I would never refer to it as such, as a Wrapper API, but that is succinct in case it were up for debate with someone, sure!

 

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
KisukaKiza
Shopify Partner
38 0 34

For those trying to figure out how to implement this having built your app using the Node + Koa + Next + Apollo tutorial featured on Shopify:

  • Apollo Boost was deprecated in July 2020. You should remove boost and install the following instead:
    • apollo-client
    • apollo-link-http
    • apollo-cache-inmemory
    • @Apollo/react-hooks
  • You'll also want to replace @shopify/app-bridge-react with @shopify/app-bridge. Create the app bridge in your _app.js using the createApp function. Then pass that to authenticatedFetch as the fetch operation function for HttpLink. Set credentials on the HttpLink to 'omit'.

  • Create the apollo client by using apollo-client, pass the HttpLink to the apollo client as a link. Set cache to InMemoryCache.

  • Using the apollo provider from @Apollo/react-hooks, set the apollo client prop.

For the server-side. You will need to remove the Koa Auth package and write your own oauth method. You can simply take the koa auth package and strip out the parts that do a bunch of cookie things before it's oauth process begins.

You'll want to perform the JWT verification on your /graphql endpoint for your graphql proxy. You will also need to store the store's access token you get during the oauth callback in a database and retrieve that access token to make the call to graphQL.

The basic flow:

  • Merchant installs or visits your app, /auth is visited. This triggers the start of your oAuth process, you need to generate an auth URL. You can use the shopify-token package to do this.

  • Once approved, the merchant is sent to your redirectUri / Callback. On here you store the merchant's access token to your database. If it's an offline token it lasts forever, if it's online it expires after 24 hours currently. Set an expire time, you will also wanna store the user's user id if it's an online token. At this stage you also register your webhooks and perform your shop plan / charge checks. At the end of this process you should perform redirects to your app homepage.

  • When you perform a graphQL query on your frontend, it makes a call to /graphql on your app, sending the JWT token with it in an authorization header. On the server send, you will want to either replace the graphQL proxy middleware with your own or perform a check beforehand. You will want to validate the JWT token, if it's valid you grab the latest access token for that store or user. You can pull it from your DB using the 'sub' variable within the JWT payload for user_id, or can use the shop variable.

  • Once you pull the access token from your database for that store / user, pass it to your graphQL proxy function. You should pass the shop and access token to this function. This will perform the graphql query on the shop using the access token. It'll then return the results to the frontend.

Some other things to be aware of: You may want to perform a "check if this is a known shop" anytime a shop accesses your app. You perform a query to see if they have any valid access tokens in your database. If they're not a known shop, pass them to the oauth start process.

Regarding "How do I get the shop parameter into my frontend?" You don't have to pass it via a cookie. Anytime a merchant accesses your app, a shop query parameter is passed with it. If you are creating links within your frontend, make sure you are also appending the shop query parameter to the end of your links using that query parameter.

dsingh
Shopify Partner
13 0 3

I was playing around with the JWT tokens issued by Shopify. This seems like a great solution to get around the recent 3rd party cookies issues. However, I do have a few questions.

  1. I'm guessing that this only supports online tokens? When I decode the JWT token I'm getting a user id and I think partners get shop id when requesting offline tokens? (Please correct me if I'm wrong)
  2. Are we supposed to match against shop's myshopify domain? If so, maybe getSessionToken() should support a parameter to receive authenticated shop id instead?

Can you please provide some clarification on this?

KisukaKiza
Shopify Partner
38 0 34

@dsingh JWT is separate from the access token. You generate the access token, online or offline, during your oauth callback and handle storing it in your db depending on if it's online or offline. You always should be storing the myshopify domain imo. If you are doing offline tokens, match it up with the access token via the domain name and make your shop domain column in your db a unique constraint. Basically just ignore the sub field from jwt if offline. The sub is always the user id of user who that jwt token is for.

dsingh
Shopify Partner
13 0 3

@KisukaKiza My concern is security related here. i.e. Are the shopify domains recycled? or changed? If answer to either of those questions is yes then it'll break the authentication process if we're matching based on shopify domain.

dsingh
Shopify Partner
13 0 3

@Liam FYI ^^ Please see my post above.

KisukaKiza
Shopify Partner
38 0 34

@dsingh In the 5 years I've used Shopify I've never seen a myshopify url changed or recycled into a new store. When you try to signup using one that was ever used before it gives an error. Even if it were recycled at some point, in that scenario, you should be processing the web hook you receive a few days after any app is uninstalled and wipe out all the data for that store. 

HunkyBill
Shopify Partner
4853 60 568

A few days! Heck, it should be dealt with prompter than that. When a shop closes, and Shopify sends the App Uninstalled webhook, we're talking mere minutes at the most! Why wait around days! It is likely that recycling those names is possible, but I would not stress on it either, as you always start with a fresh slate of name, and ID's if you're doing it right.

I think I still own flowers.myshopify.com and cars.myshopify.com if anybody wants... haha. Going back to 2006 I bet. When it failed to occur to me that shop domain name matters for nothing save it is the unique ID of the shop.

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
dsingh
Shopify Partner
13 0 3

@HunkyBill Agreed, I'd prefer to use the shop id (just to be certain). But We can't depend on callbacks for data security. Callbacks fail, endpoints can be unavailable, etc. FWIK I think that JWT only gives us the user id for the active user and the shop url/domain. That probably isn't the best information to authenticate using JWT. Does that makes sense?

HunkyBill
Shopify Partner
4853 60 568

I am not going to argue for or against JWT. If a couple of billion dollar companies decided it was OK to use them, and the code provided to use them was not written by me, but by experts in that domain, I leave it to them that it just works. Rolling your own always involves mistakes and holes, so I leave you to decide for yourself what you do. I just know that webhooks are retried till they succeed, or the webhook is deleted because the App never responded in a good many days.

 

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
dsingh
Shopify Partner
13 0 3

@HunkyBill I'm not arguing for or against JWT.  There is no issue with that. What I'm saying is that maybe Shopify should pass the Shop ID, instead of User ID in the JWT token. We(partners) don't receive the User ID during the OAuth process. The ID which we get through OAuth is the Shop ID (AFAIK).

OAuth

- We're receiving Shop ID and Shop Domain

JWT Auth

- We're receiving User ID and Shop Domain

HunkyBill
Shopify Partner
4853 60 568

Ok cool. I am surprised Shopify would screw up the basics, but it what you're pointing out is a basic screwup, then best it get sorted now, before everyone gets pumped and primed and then lost due to this. I think you can setup a flow where you do get a UserID, but certainly not everyone uses that, so it remains a fringe benefit, not the main course meal. 

Custom Shopify Apps built just for you! hunkybill@gmail.com http://www.resistorsoftware.com
KisukaKiza
Shopify Partner
38 0 34

I think you both aren't understanding the point of JWT. It's stateless authentication. It has no knowledge if you are storing offline or online access tokens behind the scenes. A JWT sub will always be a user id because it's the user who is invoking the action. If it's an offline token, simply use the domain to pull the token via the domain. myshopify domains don't recycle and cannot be changed. You can add an uninstall webhooks that trigger right at uninstall and you also receive revoke webhooks automatically if you don't have an uninstall webhook. You're making it way more confusing than it needs to be.

Offline token? Use `dest` for the check to grab the offline token.

Online token? Use `sub`.

Hell you could even make another table that associates user_ids with a specific domain.