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.
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.
The problem seems to be you can only log into one browser tab / browser at a time. That’s unexpected and should be fixed.
Signup a new user
click link in an email which opens a second tab where logged in and can access /applicant
logout and close tab
switch to original tab and login
/applicant 404s
Ctr+F5 and page loads
Thant irratating but not a deal breakerl
open edge while still logged into firefox.
log in same user
/applicant 404s
ctrl F5 does nothing, even after waiting a bit
log out in firefox
Ctrl F5 and still 404s in edge
logout of edge and log in again - stil 404
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
logging into in two browsers usually results in failure in 2nd, sometimes failure in both.
Ctrl+F5 sometimes gets it working - pressumably a new cookie is given.
I expect the other ideterminite states are simlpy do with incorrect cookies and my missing the exact state changes.
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.
go to the gated applicant page when logged out - you get 404 s expected
login (which does not change the page) and still get 404
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)
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
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 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 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.
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
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 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
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)
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
go widget client side - I guess you know what it does, if anything
go widget server side / identity - I’ve no idea if there is anyhting happening there
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
Forms - don’t care AFAIKS
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?
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.
All of that happening at the same time is hurting my head
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
# 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!
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.
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.
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
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 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
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
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
Always welcome This has been a fun, albeit head-scratching, investigation. Hoping it drives forward to something great for more than just us
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.
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.