how to use an Axios interceptor with Next-Auth
Asked Answered
H

3

7

I am converting my CRA app to Nextjs and running into some issues with my Axios interceptor pattern.

It works, but I am forced to create and pass an Axios instance to every api call.

Is there a better way to do this?

Here is what I have now:

Profile.js:

import { useSession } from 'next-auth/react'

function Profile(props) {
    const { data: session } = useSession()
    const [user, setUser] = useState()
    useEffect(()=> {
      const proc= async ()=> {
        const user = await getUser(session?.user?.userId)
        setUser(user)
      }
      proc()
    },[])
    
    return <div> Hello {user.userName}<div>
}

getUser.js:


export default async function getUser(userId) {
    const axiosInstance = useAxios()
    const url = apiBase + `/user/${userId}`
    const { data } = await axiosInstance.get(url)
    return data
}

useAxios.js:

import axios from 'axios'
import { useSession } from 'next-auth/react'

const getInstance = (token) => {
    const axiosApiInstance = axios.create()

    axiosApiInstance.interceptors.request.use(
        (config) => {
            if (token && !config.url.includes('authenticate')) {
                config.headers.common = {
                    Authorization: `${token}`
                }
            }
            return config
        },
        (error) => {
            Promise.reject(error)
        }
    )

    return axiosApiInstance
}

export default function useAxios() {
    const session = useSession()
    const token = session?.data?.token?.accessToken
    return getInstance(token)
}

Hendeca answered 20/2, 2022 at 15:21 Comment(0)
H
10

In case anyone else has this problem, this was how i solved it (using getSession):

credit to: https://github.com/nextauthjs/next-auth/discussions/3550#discussioncomment-1993281

import axios from 'axios'
import { getSession } from 'next-auth/react'

const ApiClient = () => {
    const instance = axios.create()
    instance.interceptors.request.use(async (request) => {
        const session = await getSession()

        if (session) {
            request.headers.common = {
                Authorization: `${session.token.accessToken}`
            }
        }
        return request
    })

    instance.interceptors.response.use(
        (response) => {
            return response
        },
        (error) => {
            console.log(`error`, error)
        }
    )

    return instance
}

export default ApiClient()
Hendeca answered 20/2, 2022 at 16:5 Comment(3)
It does not look good because it issues session API request on every axios request.Antipus
Agree. This solution sends dozens of the same requests.Banal
i ended up abandoning converting to nextjs because I was unhappy with this. But I am gearing up to try it again since I've learned a lot since this. Thinking about trying with-iron-session insteadHendeca
F
2

There is actually a neat way on including user extended details to session object

// /api/[...nextauth].ts
 ...
 callbacks: {
        session({ session, user, token }) {
            // fetch user profile here. you could utilize contents of token and user
            const profile = getUser(user.userId)

            // once done above, you can now attach profile to session object
            session.profile = profile;

            return session;
        }
    },

The you could utilize it as:

const { data: session } = useSession()

// Should display profile details not included in session.user
console.log(session.profile)
Floeter answered 2/11, 2022 at 18:21 Comment(0)
L
-2

I know one way to do this is to use

const session = await getSession()

Is there any other way to go about it without using await getSession() because what this does is that it makes a network request to get your session every time your Axios request runs?

Littrell answered 31/10, 2022 at 10:12 Comment(1)
If you have a new question, please ask it by clicking the Ask Question button. Include a link to this question if it helps provide context. - From ReviewPapoose

© 2022 - 2024 — McMap. All rights reserved.