Skip to content

Commit 17266ab

Browse files
fix(ui): tokenInMemory not set after refreshing cookie (#15928)
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`). <!-- 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>
1 parent 80ae745 commit 17266ab

3 files changed

Lines changed: 32 additions & 3 deletions

File tree

packages/ui/src/providers/Auth/index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import { useRouteTransition } from '../RouteTransition/index.js'
1818
export type UserWithToken<T = ClientUser> = {
1919
/** seconds until expiration */
2020
exp: number
21-
token: string
21+
refreshedToken?: string
22+
token?: string
2223
user: T
2324
}
2425

@@ -155,7 +156,7 @@ export function AuthProvider({
155156

156157
if (userResponse?.user) {
157158
setUserInMemory(userResponse.user)
158-
setTokenInMemory(userResponse.token)
159+
setTokenInMemory(userResponse.token ?? userResponse.refreshedToken)
159160
setTokenExpirationMs(userResponse.exp * 1000)
160161

161162
const expiresInMs = Math.max(

test/auth/AuthDebug.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import React, { useEffect, useState } from 'react'
88

99
export const AuthDebug: React.FC<UIField> = () => {
1010
const [state, setState] = useState<null | undefined | User>()
11-
const { user } = useAuth()
11+
const [refreshCount, setRefreshCount] = useState(0)
12+
const { refreshCookieAsync, token, user } = useAuth()
1213

1314
useEffect(() => {
1415
const fetchUser = async () => {
@@ -30,6 +31,18 @@ export const AuthDebug: React.FC<UIField> = () => {
3031
<div id="auth-debug">
3132
<div id="use-auth-result">{user?.custom as string}</div>
3233
<div id="users-api-result">{state?.custom as string}</div>
34+
<div id="use-auth-token">{token as string}</div>
35+
<div id="refresh-count">{refreshCount}</div>
36+
<button
37+
id="refresh-auth-cookie"
38+
onClick={async () => {
39+
await refreshCookieAsync()
40+
setRefreshCount((c) => c + 1)
41+
}}
42+
type="button"
43+
>
44+
Refresh auth cookie
45+
</button>
3346
</div>
3447
)
3548
}

test/auth/e2e.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,21 @@ describe('Auth', () => {
311311
await expect(page.locator('#use-auth-result')).toHaveText('Goodbye, world!')
312312
})
313313

314+
test('should keep token populated in `useAuth` after refreshing the cookie', async () => {
315+
await page.goto(url.account)
316+
const token = page.locator('#use-auth-token')
317+
const refreshCount = page.locator('#refresh-count')
318+
319+
await expect(token).toHaveText(/.+/)
320+
await expect(refreshCount).toHaveText('0')
321+
322+
await page.locator('#refresh-auth-cookie').click()
323+
324+
await expect(refreshCount).toHaveText('1')
325+
326+
await expect(token).toHaveText(/.+/)
327+
})
328+
314329
// Need to test unlocking documents on logout here as this test suite does not auto login users
315330
test('should unlock document on logout after editing without saving', async () => {
316331
await page.goto(url.list)

0 commit comments

Comments
 (0)