Skip to content

Commit 66e50fc

Browse files
committed
fix: Refresh authjs session cookie at payload "refresh-token" endpoint
1 parent d5e5d9e commit 66e50fc

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import NextAuth from "next-auth";
2+
import type { Endpoint, PayloadRequest } from "payload";
3+
import { generatePayloadCookie, headersWithCors, refreshOperation } from "payload";
4+
5+
import { withPayload } from "../../../authjs/withPayload";
6+
import { AUTHJS_STRATEGY_NAME } from "../../AuthjsAuthStrategy";
7+
import type { AuthjsPluginConfig } from "../../plugin";
8+
import { getRequestCollection } from "../../utils/getRequestCollection";
9+
10+
/**
11+
* Override the default refresh endpoint to refresh the authjs session cookie
12+
*
13+
* @see https://payloadcms.com/docs/authentication/operations#refresh
14+
* @see https://github.com/payloadcms/payload/blob/main/packages/payload/src/auth/endpoints/refresh.ts
15+
* @see https://github.com/payloadcms/payload/blob/main/packages/payload/src/auth/operations/refresh.ts
16+
*/
17+
export const refreshEndpoint: (pluginOptions: AuthjsPluginConfig) => Endpoint = pluginOptions => ({
18+
method: "post",
19+
path: "/refresh-token",
20+
handler: async req => {
21+
// --- Payload cms default logic ---
22+
const collection = getRequestCollection(req);
23+
const { t } = req;
24+
25+
const headers = headersWithCors({
26+
headers: new Headers(),
27+
req,
28+
});
29+
30+
const result = await refreshOperation({
31+
collection,
32+
req,
33+
});
34+
35+
if (result.setCookie) {
36+
const cookie = generatePayloadCookie({
37+
collectionAuthConfig: collection.config.auth,
38+
cookiePrefix: req.payload.config.cookiePrefix,
39+
token: result.refreshedToken,
40+
});
41+
42+
if (collection.config.auth.removeTokenFromResponses) {
43+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
44+
// @ts-expect-error
45+
delete result.refreshedToken;
46+
}
47+
48+
headers.set("Set-Cookie", cookie);
49+
}
50+
51+
const response = Response.json(
52+
{
53+
message: t("authentication:tokenRefreshSuccessful"),
54+
...result,
55+
},
56+
{
57+
headers,
58+
status: 200,
59+
},
60+
);
61+
62+
// --- Custom logic ---
63+
64+
// If the user is authenticated using authjs, we need to refresh the authjs session cookie
65+
if (result.user?._strategy === AUTHJS_STRATEGY_NAME) {
66+
await refreshAuthjsSessionCookie(req, response, pluginOptions);
67+
}
68+
69+
return response;
70+
},
71+
});
72+
73+
/**
74+
* Refresh the authjs session cookie
75+
*/
76+
const refreshAuthjsSessionCookie = async (
77+
req: PayloadRequest,
78+
response: Response,
79+
pluginOptions: AuthjsPluginConfig,
80+
) => {
81+
// Create authjs instance
82+
const { auth } = NextAuth(
83+
withPayload(pluginOptions.authjsConfig, {
84+
payload: req.payload,
85+
userCollectionSlug: pluginOptions.userCollectionSlug,
86+
}),
87+
);
88+
89+
// Execute authjs "auth" function to refresh the session and generate cookies
90+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
91+
const resp: Response = (await auth(req as any)) as any;
92+
93+
// Set cookies on response
94+
for (const cookie of resp.headers.getSetCookie()) {
95+
response.headers.append("Set-Cookie", cookie);
96+
}
97+
};

packages/payload-authjs/src/payload/collection/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { AuthjsPluginConfig } from "../plugin";
55
import { mergeFields } from "../utils/mergeFields";
66
import { defaultAccess } from "./access";
77
import { logoutEndpoint } from "./endpoints/logout";
8+
import { refreshEndpoint } from "./endpoints/refresh";
89
import { accountsField } from "./fields/accounts";
910
import { generalFields } from "./fields/general";
1011
import { sessionsField } from "./fields/session";
@@ -109,5 +110,7 @@ export const generateUsersCollection = (
109110
...(collection.endpoints || []),
110111
// Add the logout endpoint
111112
logoutEndpoint(pluginOptions),
113+
// Add the refresh endpoint
114+
refreshEndpoint(pluginOptions),
112115
];
113116
};

0 commit comments

Comments
 (0)