Gated content not working in Chrome (or Chredge)

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

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!


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


# 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.

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 - and your preview site uses a, 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.

:eyes: even when you’re logged in? That definitely shouldn’t be…

Yes I wanted to use google as the charity peeps all have GSuite accounts. But you dont get any events then - either in the front end or linked functions :frowning:

I’m surprised that can’t be hooked up though

The doc I linked is different from using the Google OAuth with ‘normal’ Netlify Identity – but you may not be able to see the custom JWT provider/authenticator, I do believe that’s a pro account feature

On the other hand, using Google OAuth with ‘normal’ identity is a good option too, but I have yet to test and see if event-triggered functions fire for external OAuth at all. I know you (and others) have said they don’t, but I always like to make sure for myself :+1:t2:

ah, yes, Getting mixed up.

Anyway, currentUser has always been null for me, I raised an issue. Have to use it in the on(event) handlers as is passed then. Perhaps a global script only issue? who knows. I might digg in.

So calling refresh every page is fine and pretty much what I was going to do myself by looking at token.exp

The fix to currentUser is to move it to the on login event handler.

Init might seem logical and was my first thought. The go-true init must be async as it has to call home so needs to be in the init handler, or after I guess.

Except if init is called without login then user is logged out and its a page load. if user IS logged in on a page load or refesh then login is called and the user is set. But of course we don’t need currentUser as the user is passed int oteh event handler. I don;t think currentUser is ever useful unless don;t want tot pass user down lots of functions like I do here (very react like - lol)

@jonsully so having played a bit and waited a lot for tokens to expire I no longer see any problems. The call to refresh on every page load (in login event handler) apears to have fixed it… Somewhat surprisingly that includes the gating logic.

So the only out standing issue I have is multiple logins failing - and there’s and outside chance the refresh might help there too :slight_smile: Will test.

FYI here’s my working code for abstraction layer over the identiity widge.

\0/ \0/ \0/

I can now login in on multipe browsers as same user. Will get my colleque to try to . Perhapd a combination of the routing to home of error and refresh().

I’m a happy bunny right now :slight_smile:

Thanks for helping to keep me sane through this :slight_smile:

BTW I raised a PR for the widget README

1 Like

Glad to hear it! Did you change something to get multiple browsers at the same time working? I don’t think there should’ve been any issue there :thinking:

1 Like

The only change I’m aware of (and it’s been a long journey) was the token refresh and the rule to redirect to / on a 301. Oh, I also removed the possibility of being on a gated page when you log in which was also problematic.

I suspect these worked together to remove the multi login problems that looked like Chromium issues.