Problems with Redirect JWT role-gated pages on edge

Theoretically this could work but I don’t know of any SSGs utilizing this workflow at the moment — setting it up yourself may be a nasty journey through Webpack configs :rofl: Tbh the ‘hide important data behind authorized fetches’ is very much so the common and secure practice.

No, I don’t believe this is the case. Because ultimately everyone sees the same headers and boxes around the content, so it’s fine that it’s statically available inside the bundle. The actual billing details and data are protected through authorized fetches and API calls to Netlify’s core API.

This can definitely be the case. Again, I really like my sync-to-contentful workflow, but I know it’s not for everybody. My Contentful workflow syncs the user ID, full name, and possibly email address (forgot, to be honest) over every time a user logs in (to make sure the Contentful side is always up to date), but in your case maybe you only ever need to push over the user ID to Fauna since your other interactions on the Fauna side would only need to FK to the user id.

Alternatively, I don’t think I mentioned this but it’s definitely worth mentioning - you can store arbitrary data on the user objects in Netlify Identity. With the asterisk that, since the JWTs are signed, not encrypted, so the user can technically see the contents of the entire JWT, Netlify Identity exposes two JWT fields: app_metadata and user_metadata - the latter being updatable by the user themselves, and the former only being updatable by app admins (e.g. Netlify admin UI). For example, the demo site for my open source React-Netlify-Identity connector (react-netlify-identity-gotrue) uses the user_metadata block as a means for storing additional data about the user - things they can edit like their phone number, their address, full name, etc… whereas the app_metadata block could be used to store (hypothetical) foreign keys that reference that same user in a different system (like that user’s Stripe ID so you could pass them through to an authenticated Stripe Checkout session).

All that to say, if your application doesn’t need its own data model outside of auth and just needs auth and a way of securely storing keys on users, Identity alone could do it. Just wanted to make sure you knew that you can store data on users.

Things that don’t require auth or secure data :stuck_out_tongue: HTTPS is great but it does add a few extra round trips to the server. I’m not saying I actively encourage non-SSL web usage, bu there are use cases for it :sweat_smile:

Re: the cookie-based _redirects

@slim and I worked through the _redirects stuff intensely for a number of days in another huge thread, but I don’t encourage people to go down this track unless they really know what they’re doing and accept the downsides of this method. For starters, your site has to be using gotrue-js under the hood and has to be using it very carefully as to make sure to signal GoTrue (the core API behind Netlify Identity) to send back the set-cookie header to the client. That cookie header simply contains the JWT, but since it’s an httpOnly cookie, authorized exclusively for the responding domain, things get tricky.

gotrue-js does not automatically refresh JWTs that are stale. Meaning that even though the cookie gets set in the browser, it will only correctly resolve in role-gated _redirects for one hour. After that, the JWT needs to be refreshed from the server (again, sending the ‘use-cookie’ flag so the response updates the client cookie too)… but gotrue-js doesn’t really have any plumbing to do that. You would have to build some javascript in the application-level to do some expiration-checking and force the token refresh if it’s out of date.

All of that breaks the nice UX though. If I log into a site, go to a role-gated _redirects page, then close it, go watch a movie for 2 hrs, then come back and attempt to open up that very same page, I’ll be kicked out and won’t be able to access that page until the JWT gets refreshed. Which is weird, because I’m still technically, and validly, logged in as far as JWT parlance goes. That’s not a pleasant UX but there’s no way around it since the JWT management happens in Javascript but the expiration happens in… time. So you will always get kicked out until your javascript can run (hopefully on the page you get kicked out to), refresh the token, then you can try again.

Adding to this, any site on Netlify gets provisioned one GoTrue instance. That means that local development, deploy-previews’s (from PRs in GitHub), branch-deploy’s (from long-running branches), and production all use the same Identity instance. That presents a particular issue when the set-cookie header is requiring HTTPS (local dev) and forcing the cookie to only the prod Identity instance domain. Essentially this means that getting role-gated _redirects working in non-production may be very hard. I played around with proxy-redirects and ngrok’ing a local dev server for a while but didn’t come out with strong results. This whole problem is a non-issue if you don’t use the cookie-based JWT and just use the javascript/JSON layer.

There’s a reason I didn’t include any cookie-based JWT support into react-netlify-identity-gotrue lol. It’s a massive PITA and the only benefit of role-gated _redirects is for purely-static sites that want to gate content. Since most sites using Identity (IMO) are using it with a PWA that can restrict content through a combo of client-side routing and authorized-fetching, I don’t see the cost/benefit ratio for role-gated _redirects. It just isn’t there. That’s why even Netlify CMS (which is a big PWA, essentially) uses Netlify Identity for all its needs but doesn’t prescribe that folks install role-gated _redirects to even get to the CMS login page.

Sorry for the essay. I don’t think I ever really got around to surmising my points on role-gated _redirects so probably good to get them written out somewhere.

Hope that provides some insight :slight_smile: :netliheart:


Jon