Is it expected behavior for the `useSessionContext...
# support-questions
g
Is it expected behavior for the
useSessionContext
hook from the
auth-react/recipe
to not change/cause a rerender when the accessToken expires?
r
hey @Garrett
g
howdy!
r
yes. When the access token expires, this simply means that the next request will refresh the session - it doesn't mean that the session doesn't exist anymore
g
hmmm, maybe we're doing something wrong - I'll try to explain...
We use the
jwt
from the
accessTokenPayload
as the Authorization Bearer token to make requests to our own backend.
so when that token expires, we make a request with it and our backend correctly rejects it as an expired token, causing whatever fetch it was doing to fail.
I think we originally expected the useSessionContext() hook to update the object it returns so we could access the new jwt, but based on what you just told me, that won't ever be the case.
r
oh i see. So you read the jwt from useSessionContext
hmm
normally we expect people to read the JWT by calling the getAccessTokenPayloadSecurely function which auto refreshes if needed
but i guess if you are using
useSessionContext
, then it won't cause an auto refresh
tagging @porcellus here to help
g
I could look into using that function instead
r
yea. If you use that, then it will not cause this issue
g
gotcha - still interested to hear Porcellus' thoughts since was already tagged. We're using react hooks to achieve all this behavior so it'd be very nice if there was some way to make something like this work, really helps composability of hooks etc...
a related question - what triggers an autorefresh?
p
Hi, I have to agree - the
useSessionContext
isn't supposed to be doing updates like that. If you have to have a fresh value (like in your case) you should use
getAccessTokenPayloadSecurely
directly before the call.
so these refreshes are done by the
SessionAuth
and
SupertokensAuthWrapper
components
They both provide the session context and the first time the session is constructed we check for the presence of the tokens locally and their expiration
After that, we use other events to clue us into refreshing, most prominently the backend rejecting a request with 401.
There are a few other cases, but this is the main mechanism.
I guess since you are making this request to a different backend (not the one doing the session management) this doesn't happen
g
there may be something else there, it is the same backend, we just use
hasura
so I don't think we're protecting the underlying express routes in the way you would expect. I do think that's probably why we're not getting some of the baked in features you're referring to though.
p
the interception is applied by the
apiDomain
passed to the init function in
appInfo
. If a request to
apiDomain
is rejected with a 401 it should trigger a refresh.
r
If it triggers a refresh, the old JWT will still be reused when the frontend SDK retries the original request which would cause a 401 again, and a refresh again and so on... So first, why is it not triggering a refresh? Secondly, we don't even want it to trigger a refresh cause it would cause an infinite loop...
g
so, just circling back on this - we used these docs as our guide: https://supertokens.com/docs/thirdpartyemailpassword/common-customizations/sessions/with-jwt/read-jwt#fetching-the-jwt-on-the-frontend - but you're saying that we can't always rely on that to be the most up to date access token and it would take us making a request that returns a 401 that only then it should try to refresh? Maybe another way to frame the question, since the expiration of the jwt is known on the front-end, why does it take intercepting some other request attempt to trigger a refresh?
r
Right. So the docs shouldn’t have the using react context method for this. I’ll update it. Use the without context method. That’s the correct way
If you use that method, then it will auto refresh when the getAccessTokenPayloadSecurely function is called
Also @Garrett - thanks for pointing out this issue 🙂
g
can you link the example without context method?
r
it's on the same page, same section - there is a tab for it
g
So here's the problem I think I'm having with this approach. I want to use it in a react hook. It's a common pattern to use react hooks that get a value from a global context. That way if the underlying value that the context is returning changes (a part of the session for example, in this case, the accessToken jwt), it can cascade through the hook and to whatever part of the app that cares about it. In this particular instance, a fetcher, but it could just as easily be a different value from the accessToken and another part of the app like a simple React component. So if I use the "without context" approach you have here, I have to write the business logic when it needs to refresh, right? Isn't that something that fits more in the SDK?
r
You don’t need to write business logic for refreshing here cause if the access token expires, it doesn’t indicate a state change from a UX point of view - that is to say, a session still exists. So there is no need to cause rerenders. This is as opposed to the session expiring which would cause rerenders when that is detected.
So you want to fetch the access token from the session recipe (as shown above) right before making a network call (where you are calling fetch or axios)
That being said, if you really want to have stuff rerender when the access token expires, you can make you own context provider which calls getAccessTokenPayloadSecurely periodically (based on the configure access token lifetime), and passes down the fresh JWT to your components.