Search code examples
strapinext-auth

NextAuth credentials provider and Strapi - User only has email


I'm trying to use NextAuth and Strapi in my app, but NextAuth session only shows email for the user.

When I call the Strapi login API directly:

axios
    .post(`${process.env.STRAPI_URL}/api/auth/local`, {
        identifier: "email@provider.com",
        password: "test123",
    })
    .then((response) => {
        console.log("User profile", response.data.user);
     })

I get this object (response.data.user) in console:

{
  "id": 4,
  "username": "theusername",
  "email": "email@provider.com",
  "provider": "local",
  "confirmed": true,
  "blocked": false,
  "createdAt": "2022-09-18T17:02:43.581Z",
  "updatedAt": "2022-09-27T16:39:22.993Z"
}

But when I try to sign in with NextAuth:

import axios from "axios";
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";

export default NextAuth({
    // Configure one or more authentication providers
    providers: [
        CredentialsProvider({
            name: "Sign in with Email",
            credentials: {
                email: { label: "Email", type: "text" },
                password: { label: "Password", type: "password" },
            },
            async authorize(credentials, req) {
                // return (
                if (credentials == null) return null;
 
                try {
                    /* I tried `...rest` but no luck. also console log doesn't work here and I can't see the actual response from the API call */
                    const { user, jwt } =
                        (await axios
                            .post(
                                `${process.env.STRAPI_URL}/api/auth/local`,
                                {
                                    identifier: credentials.email,
                                    password: credentials.password,
                                }
                            )
                            .then((response) => {
                                return response.data;
                            })
                            .catch((error) => {
                                console.log(error.response);
                                throw new Error(error.response.data.message);
                            })) || null;

                    return { jwt, ...user };
                } catch (error) {
                    console.warn(error);
                    // Sign In Fail
                    // return null;
                }
                // );
            },
        }),
    ],
    callbacks: {
        session: async ({ session, token }) => {
            session.id = token.id;
            session.jwt = token.jwt;
            return Promise.resolve(session);
        },
        jwt: async ({ token, user }) => {
            if (user) {
                token.id = user.id;
                token.jwt = user.jwt;
            }
            return Promise.resolve(token);
        },
    },
});

I only get email for the user:

{
  "user": {
    "email": "email@provider.com"
  },
  "expires": "2022-10-27T20:03:20.177Z",
  "id": 4,
  "jwt": "somejwtcodethatichangedhereforsecurity"
}

How can I have other properties, like username, in the user returned from NextAuth?


Solution

  • It's possible, by modifying callbacks:

     callbacks: {
            session: async ({ session, token }) => {
                session.id = token.id;
                session.jwt = token.jwt;
                session.user.username = token.username /* added */
                return Promise.resolve(session);
            },
            jwt: async ({ token, user }) => {
                if (user) {
                    token.id = user.id;
                    token.jwt = user.jwt;
                    token.username = user.username /* added */
                }
                return Promise.resolve(token);
            },
        },