Skip to content

fix(ui): tokenInMemory not set after refreshing cookie#15928

Merged
GermanJablo merged 4 commits into
payloadcms:mainfrom
DanielGiljam:issue-15926--tokenInMemory-not-set-in-AuthContext-after-refreshing-cookie
Mar 25, 2026
Merged

fix(ui): tokenInMemory not set after refreshing cookie#15928
GermanJablo merged 4 commits into
payloadcms:mainfrom
DanielGiljam:issue-15926--tokenInMemory-not-set-in-AuthContext-after-refreshing-cookie

Conversation

@DanielGiljam

Copy link
Copy Markdown
Contributor

Fixes #15926.

What?

In the AuthContext, which can be consumed via the useAuth hook imported from @payloadcms/ui, there is a token property which gets set in the internal function setFullUser. This function assumes that the userResponse argument passed to it always has the token on the property .token, when in fact it exists on the property .refreshedToken when the function is invoked after the auth cookie has been refreshed. Because of this useAuth().token is often nullish when it shouldn't be.

Why?

I want to be able to rely on the useAuth hook. Now I can't (or at least not on the token property), because there's a bug related to it.

How?

I changed the type for the userResponse parameter (UserWithToken) to convey that sometimes it's .token and sometimes it's .refreshedToken. Then I set the token property (the tokenInMemory state) to either userResponse.token or userResponse.refreshedToken depending on which property exists on the object (userResponse).

@DanielGiljam DanielGiljam changed the title fix(auth): tokenInMemory not set after refreshing cookie fix(ui): tokenInMemory not set after refreshing cookie Mar 12, 2026
@GermanJablo

Copy link
Copy Markdown
Contributor

While the PR is small, it’s a bit hard to clearly understand the What and the Why behind it.

You do explain it in the PR description, but mostly at a very low level, focusing on the surrounding code and the technical details of the change.

What would really help us review and approve the PR faster is a description from a more user-oriented perspective explaining what the actual problem is.

For example:

  • How did you run into this bug?
  • Were you trying to do something specific?
  • What steps reproduce the issue?
  • What is the current behavior vs the expected behavior in that flow?

We have an issue template that asks for this type of information, but the associated issue didn’t follow it. If possible, adding a test would also be very helpful.

Thanks a lot!

@DanielGiljam

Copy link
Copy Markdown
Contributor Author
  • How did you run into this bug?

I tried to use the useAuth hook in custom view for an app I'm developing.

  • Were you trying to do something specific?

I was trying to read the .token property of the object that's returned by the hook.

  • What steps reproduce the issue?

Use the useAuth hook. Console log the object returned by it to verify that the client is authenticated and the .token property is set. Then, call either .refreshCookie or .refreshCookieAsync. Console log the object again and notice that the .token property is no longer set, even though the cookie was successfully refreshed and the client is still authenticated.

  • What is the current behavior vs the expected behavior in that flow?

Current behavior is that the .token property isn't being set all the time, even though the client is authenticated. (More precisely, it's set at first, but then it's unset when the cookie is refreshed.) Expected behavior is that the .token property would be set all the time when the client is authenticated.

@DanielGiljam

Copy link
Copy Markdown
Contributor Author

It is quite obvious what's going wrong if you look at the code for the useAuth hook and compare that with the actual shapes of the responses you get from GET /api/:collection/me and POST /api/:collection/refresh-token.

The code currently assumes that both endpoints respond with { token } when in fact only /me responds with that and /refresh-token responds with { refreshedToken }.

So that is what I fixed in this PR. 😊 Now the code accounts for the difference in shape between the responses.

DanielGiljam and others added 2 commits March 25, 2026 09:23
…ment

- Updated `AuthProvider` to handle both `token` and `refreshedToken` more flexibly.
- Modified `AuthDebug` to display the current token and added a button to refresh the auth cookie, ensuring the token remains populated after refresh.
- Added an end-to-end test to verify that the token is retained after refreshing the cookie.
GermanJablo
GermanJablo previously approved these changes Mar 25, 2026

@GermanJablo GermanJablo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the UserWithToken signature so that it doesn't require a refreshedToken or token because that's not always the case, and I added a test. Thanks.

toHaveText() requires a string or regex argument. Use a refresh
counter to synchronize with the async refresh before asserting.
@GermanJablo GermanJablo enabled auto-merge (squash) March 25, 2026 17:47
@GermanJablo GermanJablo merged commit 17266ab into payloadcms:main Mar 25, 2026
451 of 456 checks passed
@github-actions

github-actions Bot commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

🚀 This is included in version v3.81.0

milamer pushed a commit to milamer/payload that referenced this pull request Apr 20, 2026
…15928)

Fixes payloadcms#15926.

### What?

In the `AuthContext`, which can be consumed via the `useAuth` hook
imported from `@payloadcms/ui`, there is a `token` property which gets
set in the internal function `setFullUser`. This function assumes that
the `userResponse` argument passed to it always has the token on the
property `.token`, when in fact it exists on the property
`.refreshedToken` when the function is invoked after the auth cookie has
been refreshed. Because of this `useAuth().token` is often nullish when
it shouldn't be.

### Why?

I want to be able to rely on the `useAuth` hook. Now I can't (or at
least not on the `token` property), because there's a bug related to it.

### How?

I changed the type for the `userResponse` parameter (`UserWithToken`) to
convey that sometimes it's `.token` and sometimes it's
`.refreshedToken`. Then I set the `token` property (the `tokenInMemory`
state) to either `userResponse.token` or `userResponse.refreshedToken`
depending on which property exists on the object (`userResponse`).

<!--

Thank you for the PR! Please go through the checklist below and make
sure you've completed all the steps.

Please review the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository if you haven't already.

The following items will ensure that your PR is handled as smoothly as
possible:

- PR Title must follow conventional commits format. For example, `feat:
my new feature`, `fix(plugin-seo): my fix`.
- Minimal description explained as if explained to someone not
immediately familiar with the code.
- Provide before/after screenshots or code diffs if applicable.
- Link any related issues/discussions from GitHub or Discord.
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Fixes #

-->

---------

Co-authored-by: German Jablonski <GermanJablo@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tokenInMemory not set in AuthContext after refreshing cookie

2 participants