Skip to content

Commit

Permalink
feat(auto-refresh): copy cookies to the request object as well
Browse files Browse the repository at this point in the history
In Next versions prior to 14.2.8, the cookies function (which we use for session management) reads the Set-Cookie header from the *request* object, not the *response* object. In order to get the new cookies to the request, we need to copy them over.
  • Loading branch information
Yoshify committed Dec 18, 2024
1 parent 7ce9b83 commit 508a8de
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 2 deletions.
11 changes: 9 additions & 2 deletions src/authMiddleware/authMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { sessionManager } from "../session/sessionManager";
import { getSplitCookies } from "../utils/cookies/getSplitSerializedCookies";
import { getIdToken } from "../utils/getIdToken";
import { OAuth2CodeExchangeResponse } from "@kinde-oss/kinde-typescript-sdk";
import { copyCookiesToRequest } from "../utils/copyCookiesToRequest";

const handleMiddleware = async (req, options, onSuccess) => {
const { pathname } = req.nextUrl;
Expand Down Expand Up @@ -56,7 +57,6 @@ const handleMiddleware = async (req, options, onSuccess) => {

try {
refreshResponse = await kindeClient.refreshTokens(session);
await session.setSessionItem("access_token", refreshResponse.access_token)
kindeAccessToken = refreshResponse.access_token

// if we want layouts/pages to get immediate access to the new token,
Expand All @@ -66,6 +66,12 @@ const handleMiddleware = async (req, options, onSuccess) => {
resp.cookies.set(cookie.name, cookie.value, cookie.options);
})

// copy the cookies from the response to the request
// in Next versions prior to 14.2.8, the cookies function
// reads the Set-Cookie header from the *request* object, not the *response* object
// in order to get the new cookies to the request, we need to copy them over
copyCookiesToRequest(req, resp)

if(config.isDebugMode) {
console.log('authMiddleware: access token refreshed')
}
Expand Down Expand Up @@ -105,7 +111,6 @@ const handleMiddleware = async (req, options, onSuccess) => {
refreshResponse = await kindeClient.refreshTokens(session);
}

await session.setSessionItem("id_token", refreshResponse.id_token)
kindeIdToken = refreshResponse.id_token

// as above, if we want layouts/pages to get immediate access to the new token,
Expand All @@ -115,6 +120,8 @@ const handleMiddleware = async (req, options, onSuccess) => {
resp.cookies.set(cookie.name, cookie.value, cookie.options);
})

copyCookiesToRequest(req, resp)

if(config.isDebugMode) {
console.log('authMiddleware: id token refreshed')
}
Expand Down
22 changes: 22 additions & 0 deletions src/utils/copyCookiesToRequest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { RequestCookies } from "next/dist/server/web/spec-extension/cookies";

import { ResponseCookies } from "next/dist/server/web/spec-extension/cookies";
import { NextResponse } from "next/server";

import { NextRequest } from "next/server";

export const copyCookiesToRequest = (req: NextRequest, res: NextResponse) => {
const setCookies = new ResponseCookies(res.headers);
const newReqHeaders = new Headers(req.headers);
const newReqCookies = new RequestCookies(newReqHeaders);
setCookies.getAll().forEach((cookie) => newReqCookies.set(cookie));

// NextResponse.next will set x-middleware-override-headers / x-middleware-request-* headers
const dummyRes = NextResponse.next({ request: { headers: newReqHeaders } });

dummyRes.headers.forEach((value, key) => {
if (key === 'x-middleware-override-headers' || key.startsWith('x-middleware-request-')) {
res.headers.set(key, value);
}
});
}

0 comments on commit 508a8de

Please sign in to comment.