3

I am using Next-Auth Credentials provider to authenticate using our existing API. When I follow the directions on https://next-auth.js.org/configuration/callbacks like this:

callbacks: {
        async jwt({ token, user }) {
            if (user) {
                token.accessToken = user.jwt
            }

            return token
        },
        async session({ session, token, user }) {
            session.accessToken = token.accessToken
            return session
        }
    }

the resulting session object from useSession() looks like this:

{
  expires: "2022-03-22T18:29:02.799Z",
  user: {email: '[email protected]'}
}

I can't use that as it does not have the token available.

So I was able to make up my own working solution, but it is kind of strange because of the way things are grouped together. Here is what I am doing now, that I am trying to figure out how to do better. I use comments to point out the problem areas:

[...nextauth].js:


import NextAuth from 'next-auth'
import Credentials from 'next-auth/providers/credentials'
import axios from 'axios'

export default NextAuth({
    providers: [
        Credentials({
            name: 'Email and Password',
            credentials: {
                username: { label: 'Username', type: 'text', placeholder: 'jsmith' },
                password: { label: 'Password', type: 'password' }
            },
            authorize: async (credentials) => {
                const url = process.env.API_URL + '/authenticate'
                const result = await axios.post(url, {
                    username: credentials.username,
                    password: credentials.password
                })

                const user = result.data

                console.log(user)
                //It logs this:
                /*
                  {
                    jwt: 'eyJhbasU1OTJ9.NQ356H4Odya62KmN...', //<---***This is the token i pass in to all of my API calls****
                    user: {
                            userId: 207,
                            email: '[email protected]',
                            firstName: 'John',
                            lastName: 'Doe',
                            roleId: 1,
                    }
                 }
               */

                if (user) {
                    return Promise.resolve(user)
                } else {
                    return Promise.resolve(null)                
                }
            }
        })
    ],

    callbacks: {
        async jwt({ token, user }) {
            if (user) {
                if (user.jwt) {
                    token = { accessToken: user.jwt, restOfUser: user.user }
                }
            }

            return token
        },
        async session(seshProps) {
            return seshProps
        }
    }
})


Home.js:


export const Home = () => {

    const { data: session } = useSession()
    
    console.log(session)
    //LOGS THIS --->
      /*
      {
        "session": { "user":{}, "expires":"2022-03-22T17:06:26.937Z"},
        "token":{
                "accessToken":"eyJ...",
                "iat":1645376785,
                "exp":1647968785,
                "jti":"41636a35-7b9a-42fd-8ded-d3dfgh123455a"
                "restOfUser": {
                    "userId":207,
                    "email":"[email protected]",
                    "firstName":"John",
                    "lastName":"Doe",
                    "roleId":1
                }
        }
      {
     */

    const getPosts=()=> {
       const url = 'localhost:4000/posts'
       const {data} = axios.get(url, {
          Authorization: session.token.accessToken   <--**This is the way I am calling my API
       })
       console.log(data)
    }
    
    return (
        <div onClick={getPosts}>
            Hello, {session.token.restOfUser.firstName}
/* I have to access it like this now, which seems wrong ***** */
    
        </div>
    )
}


2
  • "trying to figure out how to do better" - what exactly do you mean by that? Aren't you able to retrieve the token from useSession? Commented Feb 21, 2022 at 17:36
  • by better I mean I would rather not have to access the user via session.token.restOfUser.firstName. it's hacky
    – Jar
    Commented Feb 21, 2022 at 17:42

1 Answer 1

2

Cheers for creating your own solution but you do not need it. NextAuth CredentialsProvider handles it already by setting your NextAuth session configuration to session: {strategy: "jwt", ... }.

You can also remove your callbacks for jwt() and session() and remove your owned generated JWT access token. As you do not need it, this way you can authenticate your existing system.

And at your CredentialsProvider({authorize(){}} authorize method. If you had directly connected to the user database, you can directly look up the user credential without doing a post request since it is already considered a server-side function.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.