Next.js Discord

Discord Forum

Next-Auth help, I've been trying for so long

Answered
Devon Rex posted this in #help-forum
Open in Discord
Devon RexOP
Hi everybody,
I tried to set up next auth but its giving me problems

This is my login form
'use client';

import { signIn } from 'next-auth/react';
import { useRouter } from 'next/navigation';
import { useState } from 'react';

interface CredentialsFormProps {
    csrfToken?: string;
}

export function CredentialsForm(props: CredentialsFormProps) {
    const router = useRouter();
    const [error, setError] = useState<string | null>(null);

    const handleSubmit = async (e) => {
        e.preventDefault();
        const data = new FormData(e.target);

        const signInResponse = await signIn('credentials', {
            email: data.get('email'),
            password: data.get('password'),
            redirect: false,
        });

        console.log(data.get('email'));

        if (signInResponse && !signInResponse.error) {
            router.push('/dashboard');
        } else {
            console.log(signInResponse?.error);
            setError("Invalid credentials. Please try again.")
        }
    }

    return (
        <form className='' onSubmit={handleSubmit}>
            {error && (
                <span className=''>{error}</span>
            )}

            <input type='email' name='email' placeholder='Username or Email' required className=''></input>
            <input type='password' name='password' placeholder='Password' required className=''></input>
            <button type='submit' className=''>Log in</button>
        </form>
    );
}
Answered by Northeast Congo Lion
export default async function Home() {

    const session = await getServerSession(authConfig)

    if (session)
        return (redirect("/ai"));

    return (
        <main className="bg-white">
        </main>
    );
}
View full answer

365 Replies

Devon RexOP
"use client";

import { NextAuthOptions, User, getServerSession } from "next-auth";

import CredentialsProvider from 'next-auth/providers/credentials';

import prisma from "./prisma";

import { redirect } from "next/navigation";
import { useSession } from "next-auth/react";
import { useRouter } from "next/navigation";

export const authConfig: NextAuthOptions = {
    providers: [
        CredentialsProvider({
            name: "Sign in",
            credentials: {
                username: {
                    label: "Username",
                    type: "text",
                    placeholder: "John Stone"
                },
                email: {
                    label: "Email",
                    type: "email",
                    placeholder: "john@example.com"
                },
                password: {
                    label: "Password",
                    type: "password",
                },
            },

            async authorize(credentials) {
                if (!credentials || !credentials.email || !credentials.password)
                    return null;

                const dbUser = await prisma.user.findFirst({
                    where: { email: credentials.email },
                });

                //encrypt w/ bcrypt
                if (dbUser && dbUser.password === credentials.password) {
                    const { password, createdAt, id, ...dbUserWithoutPassword } = dbUser;
                    return dbUserWithoutPassword as User;
                }

                return null;
            },
        }),
    ],
}

export async function loginIsRequiredServer() {
    const session = await getServerSession();
    if (!session)
        return redirect("/login");
}

export async function loginIsRequiredClient() {
    if (typeof window !== "undefined") {
        const session = useSession();
        const router = useRouter();
        if (!session)
            return router.push("/login");
    }
}
This is my auth.ts config
and the api route
import { authConfig } from "@/lib/auth";
import NextAuth from "next-auth/next";

const handler = NextAuth(authConfig);

export { handler as GET, handler as POST };
next-auth][error][CLIENT_FETCH_ERROR] 
https://next-auth.js.org/errors#client_fetch_error JSON.parse: unexpected end of data at line 1 column 1 of the JSON data 
Object { error: {…}, url: "/api/auth/providers", message: "JSON.parse: unexpected end of data at line 1 column 1 of the JSON data" }
app-index.js:33:22
    error webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/app-index.js:33
    error webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/react-dev-overlay/internal/helpers/hydration-error-info.js:63
    error webpack-internal:///(app-pages-browser)/./node_modules/next-auth/utils/logger.js:46
    level webpack-internal:///(app-pages-browser)/./node_modules/next-auth/utils/logger.js:81
    _callee$ webpack-internal:///(app-pages-browser)/./node_modules/next-auth/client/_utils.js:84
    Babel 11
    _fetchData webpack-internal:///(app-pages-browser)/./node_modules/next-auth/client/_utils.js:97
    fetchData webpack-internal:///(app-pages-browser)/./node_modules/next-auth/client/_utils.js:24
    _callee5$ webpack-internal:///(app-pages-browser)/./node_modules/next-auth/react/index.js:228
    Babel 7
    _getProviders webpack-internal:///(app-pages-browser)/./node_modules/next-auth/react/index.js:240
    getProviders webpack-internal:///(app-pages-browser)/./node_modules/next-auth/react/index.js:218
    _callee6$ webpack-internal:///(app-pages-browser)/./node_modules/next-auth/react/index.js:258
    Babel 7
    _signIn webpack-internal:///(app-pages-browser)/./node_modules/next-auth/react/index.js:364
    signIn webpack-internal:///(app-pages-browser)/./node_modules/next-auth/react/index.js:244
    handleSubmit webpack-internal:///(app-pages-browser)/./components/CredentialsForm.tsx:23
    React 3
I get this error everytime I try to login with the form
What is causing it
if you need more info lmk pls
you'll need to refactor ur code and move the two functions that use useSession function to a different file.
i think that might help ur issue
Devon RexOP
Thank you so much 🙏
I was watching a tutorial and I copied what he did, idk how he used useSession and the routr
strange but thanks :)
Devon RexOP
@Northeast Congo Lion do you know how to "destroy" a session
Northeast Congo Lion
Delete cookies
Or use the sign out method
But deleting cookies work as well it’s what I do
@Northeast Congo Lion But deleting cookies work as well it’s what I do
Devon RexOP
Looks like theres another problem then...

I deleted the cookies
but I always still get redirected
const session = getServerSession(authConfig)

    if (session)
        return (redirect("/ai"));
i would not put this logic inside ur next auth config file
@Northeast Congo Lion i would not put this logic inside ur next auth config file
Devon RexOP
No this is just on the login page
@Northeast Congo Lion u definitely deleted cookies?
Devon RexOP
Yep one sec
Northeast Congo Lion
double check browser cookies, sometimes people try delete httpOnly cookie from client component
Devon RexOP
Cookies arent there
Northeast Congo Lion
can u share more code?
Devon RexOP
Yes which part do you need
Northeast Congo Lion
the part causing issues
so the it still redirects u thinking the session is valid after deleting cookies.
Devon RexOP
export default function Home() {

    const session = getServerSession(authConfig)

    if (!session)
        return (redirect("/ai"));

    return (
        <main className="bg-white">
        </main>
    );
}
`
Northeast Congo Lion
so it does redirect you?
or it doesn't
Devon RexOP
It does redirect me
When the cookies are not present
Northeast Congo Lion
yeah
id expect it to
Devon RexOP
How come
Northeast Congo Lion
!session basically means if session is false
Devon RexOP
WAit
no
I jsut changed that like a few mins ago for testing
It doesn't work even when session is valid
Northeast Congo Lion
right so
can u send updated code of what should be
Devon RexOP
YEs
Give me a second
Ubuntu just crashed 🤦‍♂️
Northeast Congo Lion
also it is a good idea to check say session.user exists
Devon RexOP
Alright noted
Northeast Congo Lion
because I think session can sometimes be empty object, so i always like to specify the check on the user existing.
session?.user
Devon RexOP
export default function Home() {

    const session = getServerSession(authConfig)

    if (session)
        return (redirect("/ai"));

    return (
        <main className="bg-white">
        </main>
    );
}
The code now
Northeast Congo Lion
aight
so if u log in
and go to / what happens
Devon RexOP
It redirects me to /ai
Northeast Congo Lion
can u console.log(session) and show me
what is printed
Devon RexOP
Yeah sure
Northeast Congo Lion
perhaps ur session is not being created
Devon RexOP
Let me see
Northeast Congo Lion
no cookie no session
Devon RexOP
Secon
d
its not loggin anything
Northeast Congo Lion
sorry
export default function Home() {

    const session = getServerSession(authConfig)

    if (session)
        return (redirect("/ai"));

    return (
        <main className="bg-white">
        </main>
    );
}
is this all the code??
Devon RexOP
yeah except the imports
Northeast Congo Lion
where are ur imports for redirect, and getServerSession
oh ok
Devon RexOP
import { redirect } from "next/navigation";
import { getServerSession } from "next-auth";
strange
Northeast Congo Lion
pls can u
Northeast Congo Lion
export default async function Home() {

    const session = await getServerSession(authConfig)

    if (session)
        return (redirect("/ai"));

    return (
        <main className="bg-white">
        </main>
    );
}
Answer
Northeast Congo Lion
let me know what session prints
Devon RexOP
oh yeah that might fix the printing problem
let me try it
Northeast Congo Lion
also I should note to you, the console log will not be in browser window
it will be in terminal
Devon RexOP
ohhhhhhhhh
i was checking the browser
Northeast Congo Lion
client component log = browser
serverside functions
= terminal
Devon RexOP
yeah right
i completely forgot
Northeast Congo Lion
so api routes terminal, server component= terminal
i was confused when u said nothing
Devon RexOP
null
Northeast Congo Lion
i at least expected log of Promise<pending>
Devon RexOP
yeah makes sense
Northeast Congo Lion
so the session is null
Devon RexOP
let me log in once more just incase
Northeast Congo Lion
and can u confirm there are cookies in browser storage?
okay login & check
Devon RexOP
Oh it worked now
Northeast Congo Lion
cool
Devon RexOP
{ user: { name: undefined, email: 'test@t.com', image: undefined } }
Northeast Congo Lion
nice
Devon RexOP
now let me logout and see if it stops redirecting me
oh its working now
lets go
thank you bro
Northeast Congo Lion
no problem
u can mark as solved
Devon RexOP
alright
ah i already did it
can i do it again
Northeast Congo Lion
uhm
Devon RexOP
cool
@Devon Rex { user: { name: undefined, email: 'test@t.com', image: undefined } }
Devon RexOP
where does name and image come from?
i want to populate atleast name
Northeast Congo Lion
insude ur authorize callback
where u return user, u can set some info here
Devon RexOP
got it, thx
Northeast Congo Lion
but iirc i think u need to do some extra work to pass custom data to session
inside the callbacks: {}
Devon RexOP
alright thanks
Devon RexOP
const dbUser = await prisma.user.findFirst({
                    where: { email: credentials.email || credentials.username },
                });
Is this not enough to sign in with both email and username?
Northeast Congo Lion
not a very secure model
Devon RexOP
how come
Northeast Congo Lion
u also configured
user/email & pass
in credentials
Devon RexOP
is that wrong?
Northeast Congo Lion
so why use only 2?
well, why get the password if u wont use it...?
i dont know any site that uses email/username only
imo
Devon RexOP
oh i dont need to get the password>
Northeast Congo Lion
i advise using password at least
Devon RexOP
yeah
i want them to login with username or email and then the password
like the form should accept an email or an username
and then the password
sorry if i was unclear
Northeast Congo Lion
okay well I would do that all on a frontend side
no it make sense
but i would stagger ur submit to next auth till u have all 3.
because u could do simple fetch to check if user exists with email/user
Devon RexOP
const signInResponse = await signIn('login', {
            email: data.get('email') || data.get('username'),
            password: data.get('password'),
            redirect: false,
        });
like this?
Northeast Congo Lion
uhm
i mean yes, but again ur code is confusing
email is either using email or username
Devon RexOP
yeah how else would i do it
it didnt work either it says nvalid credentials. Please try again.
Northeast Congo Lion
so
whatever u return
from inside authorise
if u return a user object = login
if u return null = invalid
Devon RexOP
then why should i do it thru the frontend
Northeast Congo Lion
i mean if ur submitting to login at one time
with all data, its okay
but the way u explained it was different
Devon RexOP
oh my bad
so what i showed earlier should work?
yes
Devon RexOP
idk its not working
Northeast Congo Lion
console.log the values
inside authorise
confirm ur info is being passed
check terminal
Devon RexOP
alright
{
email: 'test',
password: 'psw',
redirect: 'false',
csrfToken: 'f196d140651293a53688765496ba0775ae4ac1ac0d9d1dde85b09c77c7d0c3f2',
callbackUrl: 'http://localhost:3000/login',
json: 'true'
}
Northeast Congo Lion
okay check ur logic
where u access prisma
check if ur if statements are executing, what is being returned etc.
Devon RexOP
well the login still works with email
just not username
Northeast Congo Lion
oh
Devon RexOP
yh
Northeast Congo Lion
so username is passed in as null
Devon RexOP
well theres no username field in the credentials object
just email, and when i try sign in with user, it puts the username in the email field
Northeast Congo Lion
yeah
sorry i meant if u use username field on frontend
.email is null
Devon RexOP
nah email is populated with the username
Northeast Congo Lion
right
my guess is
prisma
is checking username against email field lol...
which means username != email
Devon RexOP
yeah how would i go about fixing that
where do i even look
Northeast Congo Lion
well the fact is prisma is comparing email against username
so it'll fail
Devon RexOP
const dbUser = await prisma.user.findFirst({
                    where: { email: credentials.email || credentials.username},
                });
I did this
Northeast Congo Lion
no
it still won't work
Devon RexOP
so what should i do
Northeast Congo Lion
if u have username property inside prisma
Devon RexOP
yh
Northeast Congo Lion
so
so submit either username: username
or email:email
dont mix them up
then in authorise function, u could do
let query = {};

if (credentials.username) query.username = credentials.username;

if (credentials.email) query.email = credentials.email;

const dbUser = await prisma.user.findFirst({ where: query });
Devon RexOP
woah thanks, let me see if it works
it still didnt work for username... only email
Northeast Congo Lion
make sure
to change ur signIn()
and pass in username: and email:
don't worry if ur passing in null user or null email
Devon RexOP
ohhh right
Northeast Congo Lion
at least one should be populated, so the query will be valid
u can improve the code ofc to be more robust
Devon RexOP
 const signInResponse = await signIn('login', {
            username: data.get('username'),
            email: data.get('username'),
            password: data.get('password'),
            redirect: false,
        });
like this?
oh wait
ill change the email thing
yeah now email and username dont work
Northeast Congo Lion
check the value of query
before running the findFirst
Devon RexOP
let query: { username?: string, email?: string } = {};

                if (credentials.username !== null) query.username = credentials.username;

                if (credentials.email !== null) query.email = credentials.email;

                console.log("Query:", query);

                const dbUser = await prisma.user.findFirst({ where: query });
thats my code
Northeast Congo Lion
and terminal shows?
Devon RexOP
Query: { username: 'null', email: 'usernametest' }
POST /api/auth/callback/login 401 in 34ms
GET /api/auth/providers 200 in 30ms
GET /api/auth/csrf 200 in 10ms
Query: { username: 'null', email: 'emailtest@t.om' }
POST /api/auth/callback/login 401 in 14ms
GET /api/auth/providers 200 in 28ms
GET /api/auth/csrf 200 in 12ms
why does usernametest go into email
Northeast Congo Lion
i think there must be a value passed in from credentials
Devon RexOP
where
Northeast Congo Lion
e.g credentials.username is not null
Devon RexOP
so should i add null checks
i dont understand
Northeast Congo Lion
solution would be to modify frontned actually
so only pass email to signIn if email not null
same with usernae
so if i use email/pass, only send email/pass to signIn
if i use username/pass, only send username/pass
Devon RexOP
well how does the form know if username or email is in the field
 <form className='' onSubmit={handleSubmit}>
            {error && (
                <span className=''>{error}</span>
            )}

            <input type='text' name='email' placeholder='Username or Email' required className=''></input>
            <input type='password' name='password' placeholder='Password' required className=''></input>
            <button type='submit' className=''>Log in</button>
        </form>
this is my form
Northeast Congo Lion
i need to understand how prisma is set-up
Devon RexOP
alright what do u wanna see
prisma.ts?
Northeast Congo Lion
user schema
because right now
Devon RexOP
model User {
  id        Int       @id @default(autoincrement())
  username  String
  email     String    @unique
  password  String
  createdAt DateTime  @default(now())
}
Northeast Congo Lion
yeah so
u can't expect
only having email input
but expect to receive username value
Devon RexOP
yeah ur right
Northeast Congo Lion
then in prisma u have username/email separate columns
so comparing username == email is why it broke in first place.
Devon RexOP
so what should i do
Northeast Congo Lion
maybe u can do $or in prisma?
like where: { email: username } or { email: email }
Devon RexOP
should i remove the query stuff then
and go back to the original thing
Northeast Congo Lion
well u need to
sort of re-evaluate how ur doing everything
i dont think ur thinking the logic through properly
Devon RexOP
honestly im confused how everything is linked
Northeast Congo Lion
ur on the right track
but instead of allowing username or email
perhaps just choose one for now
Devon RexOP
yeah maybe ill implement that later
Northeast Congo Lion
lets walk before you run
Devon RexOP
smart
Northeast Congo Lion
im happy to provide u some mentoring if u need
u can add me
Devon RexOP
thanks man, ur a lifesaver
for now im going to go with an email only approach
Northeast Congo Lion
sure glad i can help
Devon RexOP
i have no idea what happened now regular auth with just email doesnt work
but my code is identical from when is was working
(atleast im pretty sure it is)
{
email: 'test@t.com',
password: 'root',
redirect: 'false',
csrfToken: 'ecbc60dbd520a5c58dcb948352bd320a2f5dd3aef3fa3588f3b163301452559b',
callbackUrl: 'http://localhost:3000/login',
json: 'true'
}
theres no reason it shouldnt be working
Northeast Congo Lion
Is the if statement passing
Devon RexOP
if (signInResponse && !signInResponse.error) {
            router.push('/ai');
        } else {
            setError("Invalid credentials. Please try again.")
        }
here is where its failing
Northeast Congo Lion
Okay I mean the if statement inside ur auth options
Devon RexOP
const signInResponse = await signIn('login', {
            email: data.get('email'),
            password: data.get('password'),
            redirect: false,
        });
oh
Northeast Congo Lion
Please check the authorise
Devon RexOP
looks fine
async authorize(credentials) {
                if (!credentials || !credentials.email || !credentials.password)
                    return null;

                console.log(credentials)

                const dbUser = await prisma.user.findFirst({
                    where: { email: credentials.email },
                });

                //encrypt w/ bcrypt
                if (dbUser && dbUser.password === credentials.password) {
                    const { password, createdAt, id, ...dbUserWithoutPassword } = dbUser;
                    return dbUserWithoutPassword as User;
                }

                return null;
            },
Northeast Congo Lion
Console log inside the if statement lol
Quickly check if it is passing
Or console the if statement equation
Devon RexOP
uh no
if (dbUser && dbUser.password === credentials.password) {
                    const { password, createdAt, id, ...dbUserWithoutPassword } = dbUser;
                    console.log("pass")
                    return dbUserWithoutPassword as User;
                }
nothing is being logged
Northeast Congo Lion
So ur if statement is failing
Figure out why and that’ll solve it
Log the user check it
Same with Password
Devon RexOP
well the credentails object
Northeast Congo Lion
Console log the user
And see what that is
Devon RexOP
im not authenticating with user anymore
only email
Northeast Congo Lion
No
Log dbUser lol
From prisma
Devon RexOP
ohhh
nothing is being logged
Northeast Congo Lion
So your user is null
Devon RexOP
how
Northeast Congo Lion
I don’t know prisma so I can’t help there
Devon RexOP
const dbUser = await prisma.user.findFirst({
                    where: { email: credentials.email },
                }); 
this isnt working then
its not finding a user with the email
Northeast Congo Lion
Does the user exist
In the database ..?
Devon RexOP
yeah i checked with an online sqlite explorer
its def there
i bet you its a really small issue
Northeast Congo Lion
And password is right?
Actually nvm
Devon RexOP
yep
Northeast Congo Lion
It’s the user find failing
Maybe
Devon RexOP
yeah
Northeast Congo Lion
Extra , in the find
See it after where:
Idk if that will cause issue tho
Syntax maybe
Devon RexOP
imagine if it was that
let me check
Northeast Congo Lion
I think ur editor should highlight
Devon RexOP
nah it still didnt work lmao
yeah it didnt highlight
gonna reset the db
didnt work :-(
Northeast Congo Lion
Huh
The code is what you had before right
Devon RexOP
well yeah i think so
i think i missed something
Invalid prisma.user.findFirst() invocation:


The column main.User.username does not exist in the current database.
huh??
WHAT IS WRONG WITH THIS
im removing prisma
ok... guess what the error
was
visual studio code displaying the code wrong, i opened the same file in notepad and the text was different
thanks vscode!!
Northeast Congo Lion
Hah
@Northeast Congo Lion Hah
Devon RexOP
Do you know how I can access the username from the session object?
Sorry for all the questions first time doing next auth
const session = await getServerSession(authConfig);
I need to get the username from this session
@Devon Rex Do you know how I can access the username from the session object?
Northeast Congo Lion
My advice if you’re learning is to read the docs first if unsure
If you can’t understand ask away in thread but docs are p good