prats
prats

Reputation: 255

Saving custom cookies using nextjs and next-auth

I am trying to understand how to save a custom cookie using next-auth(4.22.1) with nextjs (13.4.5). Outline of my auth-flow:

  1. The user authenticates using a social provider on next-auth.
  2. On successful authentication, using the signIn callback call a custom backend api (lets call it login).
  3. login will return an access_token in Authorization header and a refresh_token in set_cookie.
  4. When the UI receives a success response from login api it allows the user to move forward.

In this flow I can save the access_token in the session and subsequently use it on client side or server side, but the refresh token is not getting saved as a cookie, which is understandable as next-auth code is being executed on server side. My question is, how do I save the refresh_token and then subsequently pass it to my backend when I need a new access_token? Is the preferred method here to save the refresh token also in the session or is there something obvious that I am missing due to which the cookie is not being set? My understanding is ideally the refresh token is saved as a http_only cookie so that its included in api calls by default.

Here is my next-auth code. I have not changed any config its using the defaults.

import NextAuth from "next-auth/next";
import GithubProvider from "next-auth/providers/github";
import {User, Account, Profile } from "next-auth";
import type { NextApiRequest, NextApiResponse } from "next"

async function auth(req: NextApiRequest, res: NextApiResponse) {
  return await NextAuth(req, res, {
    providers: [
      GithubProvider({
        clientId: process.env.GITHUB_CLIENT_ID || '',
        clientSecret: process.env.GITHUB_CLIENT_SECRET  || '',
      }),
    ],
    callbacks: {
      async signIn(params: { user: User | undefined; account: Account | null; profile?: Profile | undefined; email?: { verificationRequest?: boolean } | undefined; credentials?: Record<string, any> | undefined }) {
        //console.log('signIn', user, account, profile);
        const { user, account, profile } = params;
        console.log(account?.access_token)
        try {
            const res = await fetch('http://127.0.0.1:8080/login/', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              credentials: 'include',
            },
            body: JSON.stringify({ token: account?.access_token }),
          });
          
          if (res.ok && res.headers && res.headers.get('authorization') && account) {
            const test_access_token = res.headers.get('authorization')?.split(' ')[1];
            const test_refresh_token = res.headers.get('Set-Cookie');
            account.test_access_token = test_access_token;
            //account.test_refresh_token = test_refresh_token;
            return true;
          }
        } catch (error) {
          console.log(error);
        }
        return false;
      },
      async jwt({ token, account, profile }) {
        // Persist the OAuth access_token and the user id to the token right after signin
        if (account) {
          token.test_access_token = account.test_access_token
          //token.test_refresh_token = account.test_refresh_token
          token.id = profile?.name
        }
        return token
      },
      async session({ session, token, user }) {
        // Send properties to the client, like an access_token and user id from a provider.
        if (token) {
          session.test_access_token = token.test_access_token
          //session.test_refresh_token = token.test_refresh_token
          session.user.id = token.id
        }
        
        return session
      },
    }
  });
}

export { auth as GET, auth as POST };

Upvotes: 0

Views: 3365

Answers (1)

r4bb1t
r4bb1t

Reputation: 134

The NextAuth code runs on the server-side. So cookies cannot be set because it is not a browser. I did it by logging back into the custom backend from the client-side from the redirected route when signed in (using useEffect).

Upvotes: -1

Related Questions