Gated content not working in Chrome (or Chredge)

Hopefully a proper solution will be found for all?

I’m slightly confused about that cookie isse. Surely, as the cookie is used by the edge gating logic if it is not set for preview then preview would not work. But it worked just fine for me . Plus I’m sure I always saw the cookie in branch in FFx F12 tools

At this point I need to moved on and recoup some of the time I didn’t have that I spent on this problem. :stuck_out_tongue:

So I’ll stick to main deploy and delete all the previews Hopefully everthing will then be fine - but I have doubts. Fingers crossed. This is a “proof of concept” project to flush out issues like this and see what we can safely use for a production solution.

I’m really hoping we can use the edge gating as it is an awesome USP or Netlify.

Right I think I have got somewhere. I created a new site and added a single user.

https://festive-hoover-9c12c5.netlify.app/applicant

The problem seems to be you can only log into one browser tab / browser at a time. That’s unexpected and should be fixed.

  1. Signup a new user
  2. click link in an email which opens a second tab where logged in and can access /applicant
  3. logout and close tab
  4. switch to original tab and login
  5. /applicant 404s
  6. Ctr+F5 and page loads

Thant irratating but not a deal breakerl

  1. open edge while still logged into firefox.
  2. log in same user
  3. /applicant 404s
  4. ctrl F5 does nothing, even after waiting a bit
  5. log out in firefox
  6. Ctrl F5 and still 404s in edge
  7. logout of edge and log in again - stil 404
  8. at some point I manged to get to /applicant in edge - not now though
    9 Log into Firefox and /applicant 404’s

So in this state of neither working I logged in and out of both until I got the page in edge. Then Firefox did not work

So this is very broken right now. And still rather non deterministic.

As we were trying various browsers using the same user we may or may not have logged out and I expect once we logged in twice it all went wrong again.

I hope this will get fixed ASAP. for now we’ll try loggin OUT before logging in again as same user on another browser. I hope it’s not just logging in as same user in another browser eve after loggin out.

A slight addendum. When in the state of firefox and edge logged in and it working in Edge, edge stopped on a page fresh. I logged out of both, logged into Firefox but still 404. Ctrl F5 the ncaused the page to load.

So in summary

  1. logging into in two browsers usually results in failure in 2nd, sometimes failure in both.
  2. Ctrl+F5 sometimes gets it working - pressumably a new cookie is given.
  3. I expect the other ideterminite states are simlpy do with incorrect cookies and my missing the exact state changes.

So I just adde a new user, gave them role=rdm but cannot access the /rdm route. I tried logging in and out etc. It worked fine in the old site.

To be honest, this just does not work! :frowning:
I think I’ll have to use a Function for each page and gate it with code.

That user started to work after a while. Hopefully just a glitch for that one time.

Here’s a nother failure mode tha tis a bit of an edge case as normally you won’t be in the situation.

  1. go to the gated applicant page when logged out - you get 404 s expected
  2. login (which does not change the page) and still get 404
  3. CTRl+F5 makes no differrence. Navigating home then back to applicant wotks - it might take 2 goes

So that is unusal as you would not normaly log in on a gated page and get access. It’s only as Ive been lazy with my UI and left all option available when logged out (it’s a spike after all)

You and me both :stuck_out_tongue:

Right - and only for the gating. The cookie level is fully separate from the javascript level. The javascript level just kicks off the request that comes back with the cookie. Once the cookie’s in, it no longer matters what the javascript level does; the cookie is in. All things involving role-gating with the _redirects file come from the cookie, not the javascript. We have to think of these two layers as separate and understand how they interact independently (which is tricky)

Exactly.

Yes I agree - the JWT/Javascript layer having a different expiration timer than the cookie is indeed another layer to add to the confusion… BUT I should mention that the netlify-identity-widget sets up the cookie request to have no expiration, and stores the JWT in localstorage so in essence, both have an infinite expiration - at least that matches up. When you log in, both are set to never expire. Since cookies and localstorage both persist, even across a browser restart, they’re effectively set until you log out (logging out removes both the localstorage and the response from the /logout endpoint destroys the cookie)

So luckily, the cookie and JWT timers should always be in sync. At least one thing matches :slight_smile:

Yeah. I think that’s your main issue. Again, my workaround won’t work when using the netlify-identity-widget so I’m not really sure how to fix that for you :frowning: It’s worth clarifying too - the cookie is associated to the primary domain only, but only ever actually even gets set when you’re on the primary domain. Meaning that _redirects will never work locally or on a preview deploy, because the cookie will never be set correctly on those domains (localhost and preview-deploy-x–.netlify.app)

Combining Functions & Identity is a topic I wrote a significant amount on in this other thread - combining the two makes for a really powerful experience but it’s worth understanding the workflow. Give that a read :+1:t2: feel free to post in that thread if you have questions pertaining to that topic as well.

Sending the Authorization header to a Function occurs at the Javascript level and doesn’t involve the cookies at all, so that should actually work in any environment since all of the environments correctly produce JWTs for Javascript, it’s the cookie stuff that fails when running not on the primary domain.

I fully agree. Specifically for role-gating _redirects, there are issues running on non-main.

1 Like

When you log in, both are set to never expire. Since cookies and localstorage both persist, even across a browser restart, they’re effectively set until you log out (logging out removes both the localstorage and the response from the /logout endpoint destroys the cookie)

But after an hour I find things break and I have to logout and back again to restore correct operation. I havent explored if the issue is the gating or the JWT but interstingly the JWT has exp = 3600

The widget doesn’t help. I was going to check the JWT exp and handle by using the widget refresh function. but it seems that won;t help as gating is manged by the cookie.

Maybe I can access the cookie from javascript and check the jwt within. I never tried.

To be honest though, Netlify need to handle token refresh invisibly, as they’ve made the gating invisible. There’s a growing list of things they need to fix here :slight_smile:

Once again, I started developing on a PR preview branch and the gating was just fine! IN firefox anyway. I’ll try again at some point, but for now I can live with updating the main deployment.

The title of this evergrowing thread is still OK as apart from the loggin in twice issue problems are worse in chromium based browsers.

How do we get Netlify to pickup the issues I’ve listed and look at them?

Yeah… I won’t lie, understand the JWT workflow alone is complex. It’s not clear to me what happens once it expires anyway. In the javascript everything seems to work fine and still considers the user logged in… so I don’t think it’s “expiration” in the sense that the JWT self-destructs, but perhaps an expiration timer of when GoTrue will no longer validate that JWT as being “live”? I’m not sure and I’m not a huge fan of having to wait an hour to find out :man_facepalming:t2: but that’s what this GitHub issue suggests I think. Sending a stale JWT to a Function (which validates the JWT against GoTrue before even running) is the scenario there… but if a post-expiration-date JWT still means “You’re logged in” as far as Javascript goes and the JWT is stored in Localstorage, that should mean that once you’re logged in, you don’t ever have to re-login… as far as the javascript goes

But that’s where it disconnects. If the JWT is always valid but the cookie dies after a day, you could totally have someone login on day one, then come back to the site on day 2 and be logged in but unable to access certain pages that are role-gated in the _redirects… which feels… bad.

All of that happening at the same time is hurting my head :man_facepalming:t2:

Yeah… I won’t lie, understand the JWT workflow alone is complex

Made worse by the fact there are many flows depending on things like client security (web clients are the most insecure). As it’s largely architectural convention implementations vary and that is a weakness of OAuth / OpenID IMHO. I started with the Google docs which are Aweful!!! Auth0 do an excellent job but it’s so complex. I gave up as my communications protocol plumbing days are well over. In this case I really want it to just work without my needing to do anything in my code, and especially not spend so much effort on why it is not working!!

so I don’t think it’s “expiration” in the sense that the JWT self-destructs

Quite.The JWT is just a document and working code has to make “it expire”. And we have several things that need to do somehting to make the expiry mean anything when it gets a chance to run (and they all need to agree)

  1. Userland Frontend code - Nothing happening here, move along. But there is a refeshtoken call available. I have seen code that checks the expiration on every action and logs a user out or warns them. We should probably do that for good UX
  2. go widget client side - I guess you know what it does, if anything
  3. go widget server side / identity - I’ve no idea if there is anyhting happening there
  4. Functions - only if we send the token and then all checks are probably down to our function code checking “exp” and “aud” etc plus calling to Netlify APIs to check is valid user etc
  5. Forms - don’t care AFAIKS
  6. gating - probably checks the exp as well as roles in app_metadata but don’t know if is the same token in use or another separate one. If same then how do they get kept in sync without breakages when everyhting is event driven?
  7. Netlify API - probably supplies it’s own access tokens with own exp etc. I’ve not looked

then come back to the site on day 2 and be logged in but unable to access certain pages that are role-gated in the _redirects … which feels… bad.

I’m pretty sure that’s what I see after an hour of non use. I don’t think active use causes any difference - unless that invokes code to check. A log out and control F5 is needed to use the app. In some other broken states a F5 is need to see the gated page at all rather than 404. This is ALL bad UX, if not terrible!

I’d really like Netlify to work on these issues, or at acknowledge them. But there’s been zero engagement with this thread. Probably the size is frightening every one off. :stuck_out_tongue:

All of that happening at the same time is hurting my head

Me to. I want it to just work. Please Netlify!

Re that git hub issue

auth.currentUser().jwt()
and
But the jwt method will only refresh the token when needed, otherwise it returns the current one:

But there is no such function, document or in the widget code. Unless that is the go-true layer?

Auto refresh is what we need in the client!

and

However, Netlify functions has an identity context (with an elevated permissions token) set for them so you might not need to send the token at all. See example:
GitHub - netlify/gotrue-js: JavaScript client library for GoTrue

That is critical information that will save a lot of work when I come to securing my functions fpr production. Why is it not in the docs!

FYI @slim I am still working on this. I’m wanting to use Netlify Identity pretty extensively in upcoming projects and need to have these questions and workflow concepts hashed out before I get there, so it’s important for me too.

I don’t think any of the support engineers have the time to spin up on this thread since it’s so long and they need to be equitable in the way they spend their time helping others, but I am having a couple of direct conversations to get through a few questions. I’ll let you know how I progress :+1:t2:

1 Like

@slim I think where I’m at for your site is this: change your role-gate redirects from:

/rdm/*	      200!  Role=rdm,admin
/applicant/*  200!  Role=applicant,admin

to

# Two-step role-gate with fallback to home page
/rdm/*	      200!  Role=rdm,admin
/rdm/*   /    302!

# Two-step role-gate with fallback to home page
/applicant/*        200!  Role=applicant,admin
/applicant/*   /    302!

and add

netlifyIdentity.currentUser() && netlifyIdentity.refresh()

to the js script you have that runs when the page loads (right after netlifyIdentity.init() would be ideal). The reasoning here is that if the JWT expires or the cookie expires, the user will be redirects to the home page and in loading the home page, the .refresh() will run which should re-hydrate the token and the cookie. So they’ll get redirect to the home page then click back to /rdm/ or /applicant/ with a fresh token. That should keep things consistent. Using the netlifyIdentity.currentUser() && is just a protection so that you don’t call netlifyIdentity.refresh() when there’s no user logged in (that would pop and error I think)

Up for giving that a try?


Where I’m at for my site / framework is that I’m just not going to use role-gated _redirects. The cookie stuff is too messy and I don’t have control over it like I’d like to in order to have a solid UX. I’m going to just not use role-gated _redirects and handle everything gracefully in javascript.

1 Like

I linked this earlier but I had another very large thread with someone all around using Identity & Functions together. You will do yourself a big favor by reading it. The one thing I didn’t get around to mentioning there is just make sure you refresh the JWT on the client side before dispatching the request to a Function. I tested this morning to make sure, but if you call a Function with a stale JWT, the User object doesn’t even get passed to the function.

https://answers.netlify.com/t/questions-about-netlify-identity-serverless-functions/

1 Like

I’m wanting to use Netlify Identity pretty extensively in upcoming projects

I am incredibly greatful of that - given the current state of this - or at least the state of the docs for this. This is an awesome feature. If we get it going.

I am having a couple of direct conversations to get through a few questions. I’ll let you know how I progress

Excellent! As long as they are aware of the issues. Including the logging in twice as the same user.

Two-step role-gate with fallback to home page

Well OK. I have a 404 that simplictically handles gating blocks but now I have change the UI to not have those link. however there could still be link sharing between people with gated route. But it it goes home that’s prolly OK

netlifyIdentity.currentUser() && netlifyIdentity.refresh()

That seems really inefficient, unless it shortcus when jwt not expired. Make sense though and gets to where I planned to explore for refresh :slight_smile:

I have found that netlifyIdentity.currentUser() returns null somehtimes when everyhting is OK and I’m logged in. let’s assume that has gone away :slight_smile:

I’m going to just not use role-gated _redirects and handle everything gracefully in javascript.

Sure, with a SPA you have client side routing which I guess is even more efficient than edge gating - lol

I tested this morning to make sure, but if you call a Function with a stale JWT, the User object doesn’t even get passed to the function.

Believe me, I’m very familar with that specific error functions side and what it means :slight_smile:

I’m just polishing off my U of the CRUD for applcations and I’ll give your code a try.

Thanks VERY much once again

FYI I tried a branch deploy on my new site and the gating works fine. When I first fivist the rdm gate route . I do have to hit Ctrl F5 a couple of times to get to it

Mmmm :confused: yeah that’s not a great UX. Unfortunately I just can’t think of or see any way to get past this because the JWT that the _redirects engine reads expires after 1 hour. So if both users have logged in within an hour ago or gotten a fresh token within an hour ago, it should work, but otherwise yeah, that’s not fun. You’d have to implement some intense callback javascript to get that working smoothly

It does indeed shortcut when the JWT isn’t yet expired. It also runs in the background so shouldn’t do anything adverse to your UI. netlifyIdentity.currentUser()…and as for point 2 there… what? Lol. If currentUser() is null but you’re still showing as logged in, that’s strange. That shouldn’t ever happen in normal cases - only if you used dev tools to poke around with tokens or accidentally change something and the GoTrue layer broke but the Netlify Identity Widget layer didn’t know about it. currentUser() is just a pass-through to the GoTrue layer… so if it’s null but the N-I-W layer isn’t null (showing you as logged in) something got borked :rofl:

Haha yes; all the pages will be publicly available but will re-route as needed (and I did implement callbacks so hopefully it’s smooth!) and otherwise basically empty :slight_smile:


I honestly can’t explain that. The only idea I can think of is that since you don’t have a primary domain for your ‘prod’ site - you’re using the ____.netlify.app - and your preview site uses a ____.netlify.app, maybe the cookie is getting shared?

The cookie coming back from your Identity instance / GoTrue server shouldn’t be working for your preview app. They have different domains. I’m not sure why that’s working :thinking:

Always welcome :slight_smile: This has been a fun, albeit head-scratching, investigation. Hoping it drives forward to something great for more than just us

1 Like

I added you code.

I don’t call netlifyIdenity.init() I’m global script not module and the example in the readme doesn’t call init. Do you think it should? It looks like module work around stuff to me.

Anyway I added the line of code just after the widget script is loaded from the CDN.

Note: this gets called on EVERY page load. I get the impression you thought it aught to get loaded only on home?

And yes, that console log shows currentUser is ALWAYS null :frowning:

Btw, perusing though the docs, it is available to use your own/external JWT provider. That would potentially allow you/us to better control the expiration date on a JWT and/or cookie (potentially). Something worth investigating in the future perhaps Role-based access control with JWT | Netlify Docs


Sorry- I forgot that it runs automatically when you pull it in that way. As long as the code I gave you runs after that point, you should be fine. Yes it runs on every page load, which is also fine. The short-circuit makes it super super fast. You could potentially wrap it in an async function and put it at the bottom of the <body> but I don’t think there’s a lot of gain there.