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.
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.
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) ?
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?
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!
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.
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