Gated content not working in Chrome (or Chredge)

Just wanted to say that role-based redirect rules do work with Identity even on the Starter plan. What won’t work is gating using a external JWT as mentioned here:

1 Like

That’s awesome! And thank you for confirming. I’m a happy user!

For now I’m not using external Some ofthe users will be on the charity GApps so it would make sense. But we don’t get the function trigers which is sersious pain. I was thinking of coding frotd end calling the functions but now i know gating wont work I wont bother. After all it only saves a few people typing in their email address :slight_smile:

Could I suggest this pricing point is clarfied? I was obviously not the only one who read it as only gating is only available on Business. I only tried as Jason mentioned I could use it.

So where do we stand with it NOT working on chromium based browsers? Ie the title of this topic. Surely that should not be a problem at all?

Dang! That’s awesome! Good for Netlify :sunglasses: that’s super cool.

@slim I’ve spent a significant amount of time working with gotrue-js and @swyx’s react integration layer react-netlify-identity over the last several days. Let’s chat through what you’re seeing. The workflow has a few steps and I want to make sure they’re getting executed correctly.

Remind me what framework you’re using for the site in the first place - is it just vanilla static files? Then what are you using for the front-end auth layer? The standard netlify-identity-widget package?


Thanks for sticking with this! I realy appreciate it.

Yes, static files generate with 11ty
And standard netlify-identify-widget,

If you let me have you guithub id (assume you have one) I can add you to the private repo. I plan to make it open source but want to check the Charity are OK with that (though I own the IP)

No worries.

No need to add me to the repo - it’s better if things stay in public for documentation’s sake!

When it comes to roles though, can you walk me through the process you’re doing for assigning roles and how you expect the user process to go? I can tell you off the bat that I don’t think it’s going to be possible for role-based… anything to work unless the user has confirmed their account via either the confirmation email or invite email (if you invite from the Netlify dashboard)

Are you using the identity-signup hook to assign roles to users at that point?


No need to add me to the repo - it’s better if things stay in public for documentation’s sake!


When it comes to roles though, can you walk me through the process you’re doing for assigning roles and how you expect the user process to go

Sure, in geenral I kept to documented/supported stuff with minimal customisation

  • Self sign up users (not invite)
  • Default netlify-identity-widget - only cutomisation is hiding at various stages and a page change on logout
  • role set by returning from identity-signup & identity-signup. Role can change over time so need to login too. I spent some time exploring the states and events with login/out, browser refresh etc
  • have custom 404 in case can’t access a route.
exports.initAppMetadata = async function initRoles(event, context) {
  const { user } = JSON.parse(event.body)
  const { roles: currentRoles } = user.app_metadata
  let body = {}

    if (!currentRoles || currentRoles.length == 0) {
      body = {
        body: JSON.stringify({ app_metadata: { roles: ['applicant'] } }),

  return { statusCode: 200, ...body }

UX is

  • /applicant route is unavailable due to gating
  • signup
  • confirm email
  • login (can’t recall now if this done by system - but in another window)
  • has role ‘applicant’ assigned (by above code)
  • can access /applicant

That’s it. Any insights?

I just tested and it works in Firefox and NOW ALSO Chrome, but not Edgium. I tried logging out of other browsers, using icognito tabs etc etc. I really don’t understand how browser can change the behaviour.

That all seems good from my eyes - can you confirm that the applicant role is indeed being applied to users after confirming their email? You should be able to see the users and their roles on the Netlify dashboard as a double-check measure


Thanks john - I just tested with similifed code too as that calls the google sheets API

It works in Firefox and NOW ALSO Chrome, but not Edgium. I tried logging out of other browsers, using icognito tabs etc etc. I really don’t understand how browser can change the behaviour.

Good point - as we set role if empty. let me check the various combinations

so now I’m officially confused.

  • I deleted the applicant role in the Netlify dashboard
  • logged in edgium and IT NOW WORKED
  • logged in with Chrome and it now fails again!

I tried deleting again and logging in with Chrome 1st. No change. Firefox always works


PS I also tried closing other browsers after logging them out. There’s probably one critical permitation/sequence I’ve not yet tried. I hate this sort of bug.

Oh boy!

I’m now logged into Chrome, edge and firefox.

  • seems it’s not how many browsers are logged in
  • unlikely to be a race condition as I in all cases I clicked to gated route immediately I get logged in.

So one possbility is being logged in from local host at same time. Currently am not. Previously was When I get some more time I explore that.

Thanks for your patience

Oh, I also checked the roles in dashboard at every step. Always set and I even clicked edit to check is there (to eliminate white space problems, well possibly)

Some one else was getting the odd problem on Firefox and now i try I’m only getting it working on FFx as before.


Assuming noone else has problems I’m going to have to try starting a new project or ripping stuff out of this one. What a pain!


I think what you may be experiencing is related to the fundamental principle of how JWT’s work. JSON Web Token are a form of stateless auth, and the contents verify themselves. Once you have one, it itself is signed and verified until it expires or you force it to reload.

So in the context of this discussion, it works like this: when you have a user sign up initially, a user is created in the Hosted Netlify Identity service (GoTrue), but it is not a confirmed user (unless you have autoconfirm enabled but it’s not enabled by default and a bit hard to enable anyway :stuck_out_tongue: ). When the user clicks the link in the email, a confirmation token is sent to GoTrue and GoTrue runs the identity-signup hook (if it exists). If that hook returns roles, those roles are applied to that user then the response from GoTrue is a full JWT for that user and gets stored in the user’s browser. The JWT’s TTL is 1 hour. It is a fully authenticated, signed, standalone stateless auth token that will validate against role-checks and role-based redirects.

If you delete that user from the Netlify dashboard at that point, it won’t matter. That JWT is still alive, still fully valid, and still contains the role data and other metadata associated to it at the time it was signed. That’s one of the side effects of stateless, signed auth tokens. Until that user logs out, the JWT times out (1 hour from last refresh), or you force a JWT refresh on the client side, that client is a fully authenticated user.

That means even after you delete the user, that user is still logged in client-side, can still successfully ping Authenticated Functions, etc…

An additional side-effect of the stateless auth is that if you change a user’s role or other data from the dashboard, it won’t necessarily update client-side until that client pulls a new Token from GoTrue. Again, you can force that, but it’s something to be aware of.

There’s a lot of opportunity for confusing workflows when running stateless auth tokens. As I recently found too - it can be more confusing if your identity-signup function is slow. When the user clicks the confirmation link, the page will load and then sit as if you’re not logged in and just loaded the public page for a second or two. Then it’ll click in with your user. This is because GoTrue calls your function synchronously and if your Function is slow, it delays the callback. Wrote some interesting code around that one… :sweat_smile:


You may be right but I’ll have to digest it more. This is happening to other user too though with a different user account.

I would expect a new token for each signin - whether in different browsers or multiple tabs in same browser.

What I just did has caused a new issue. I finally merged my branch to master. Up to now I’ve been running on a preview deployment based of a PR for the branch. I never had anyhting working on master.

The main site is actually working fine across browsers but if I now try the preview deployment It errors in the login widget saying Failed to handle signup webhook!!??

This really surprises me. Surely the auth web hook ( I assume webhook == function) is per deployment.

Also I just realised from your above comment that a single set of users shared between all deployments is going to cause strangeness.

It can but it’s all about domains. Yes it’s the same credentials, but since your preview deploy is on a different domain than your master branch (which is assumably on the domain you own), you shouldn’t get cross-cookies / same user contexts. Same with localhost.

That doesn’t hold if you’re using multiple deploy previews though, since those would all be ** I think.

Yes that error means your identity-signup Function errored out. The tough part will be figuring out why perhaps - yes I believe each deployment gets its own Functions packaged and sent to Lambda and hooked up, but I’m not totally sure how the logs viewer in the Netlify dashboard works - whether it only shows logs from your Production Functions or if it accumulates logs from all deployments?

In general, the tooling under-the-hood is all prepared and setup to have each deployment get its own context and ‘stuff’ (outside of Identity) but viewing those split out things in the Dashboard isn’t clear :thinking:


yes and the auth widget doesn’t handle token expiration at all. I see the API has refresh so I’ll explore using this at some point. For now logut followed by Ctrl+5 works in this case.

I understand what you are saying about lots of potential for confusion. And the fact that the Browser caches the token in local storage adds more possibilities.

I am not deleting any users for now but did notice they still get access but expected that via the token , as you point out. Loging out appears to delete the token from local storage so that should require fetching a new one on next login.

I’m not sure that explins theother person find out long after token expires that he cannot access a route he should be able to after logging in. I will double check with him though.

So I’m not sure how token life cycles can explain all the oddities across browsers. They should all get the same toke fom what you say and it should work in all of them.

At least I only send new roles if they are not already set. Otherwise every login would get a fresh JWT . Hmm maybe that will fix the problem - LOL

I’m adding some logging to explore

That’s reassuring you think that should be the case.

No idea why the function would start erroring . I merged code working on the brach acros and it stops working. Fun!

One really annoynce with the dash baord is the convoluted way to get to the function logs. It’s only on one UI path to view a deployment.

This is taking a frustrating amount of time but that’s what system integration is always like.

I’m just hoping we can use any browser on the main deployment. Tha twil ldo for now as this i sa proof of concept and technology testing spike! Haha

I was wondering if it takes time for the new roles to get pushed to the edge. But as I don’t change them right now that should not matter. Ubless each deployment wipes the roles - which it doesn’t appear to do.

Having added logging to watch