Reputation: 1
While rewriting an app from CRA to Next.js, I encountered an issue with using a JWT access token for client-side requests.
Previously, the token was stored in localStorage, making it easy to add to request headers as Authorization: 'Bearer ...'
.
Now, in Next.js, it's recommended to store the token in httpOnly cookies, which are inaccessible on the client side. This raises the question: how can I properly send requests on behalf of an authenticated user if cookies are inaccessible on the client, and the instance (like axios) is created on the client side?
Here’s my Next.js API where I save the token after authorization in cookies:
// api/auth/login/route.ts — Next.js API route
import { NextResponse } from 'next/server';
import axios from 'axios';
export async function POST(request: Request) {
const { token } = await request.json();
try {
const { data }: { data: OAuthResponse } = await axios.post(
`${process.env.NEXT_PUBLIC_AXIOS_BASE_DEV_URL}auth/by-google`,
{ token }
);
const response = NextResponse.json({ success: true });
response.cookies.set('auth_token', data.token, {
httpOnly: true,
secure: true,
maxAge: 30 * 24 * 60 * 60,
path: '/',
});
return response;
} catch (error) {
return NextResponse.json(
{ message: 'Authorization failed' },
{ status: 401 }
);
}
}
Here's the RTK slice where I need to insert the token into the headers:
export const authApi = createApi({
reducerPath: 'api/auth',
baseQuery: ...,
endpoints: (build) => ({
loginWithGoogle: build.mutation<OAuthResponse, OAuthRequest>({
query: (body) => ({
url: 'auth/by-google',
method: 'POST',
body,
}),
}),
fetchMe: build.query<OAuthResponse, void>({
query: () => ({
url: 'auth/me',
method: 'GET',
}),
}),
}),
});
Before Next.js, everything was extremely simple. I created an axios instance
in a separate file and could reuse it easily. It would be great to know how to implement this in Next.js.
I don't want to use libraries like next-auth
.
Upvotes: -1
Views: 240
Reputation: 896
You can use next-client-cookies
https://github.com/moshest/next-client-cookies
import { CookiesProvider } from 'next-client-cookies/server';
export default function RootLayout({ children }) {
return <CookiesProvider>{children}</CookiesProvider>;
}
'use client';
import { useCookies } from 'next-client-cookies';
const MyComponent = () => {
const cookies = useCookies();
return (
<div>
<p>My cookie value: {cookies.get('my-cookie')}</p>
<button onClick={() => cookies.set('my-cookie', 'my-value')}>
Set cookie
</button>
{' | '}
<button onClick={() => cookies.remove('my-cookie')}>Delete cookie</button>
</div>
);
};
Upvotes: 0