NextAuth CredentialProvider with T3 default Auth Prisma models limitation question.

Actually I made a sign up page using CredentialProvider using Email ID and Password. My question is, 1.) create t3 app with NextAuth has built in tables named Accounts, Session and VerificationToken. Now due to me using CredentialProvider the rest of the tables are not being used because NextAuth is limiting that intentionally. More on that here -> https://next-auth.js.org/providers/credentials Now I want to know what functionalities I am missing, and do I even need those? Because my cookies are being created in the browser and useSession is also working fine. 2.) Also please tell me if I can delete the tables which are not being used in the prisma schema made by create t3 app.
17 Replies
Hampterultimate
Hampterultimate•2y ago
If anyone wants any kind of additional info please let me know. I found this solution https://github.com/nextauthjs/next-auth/discussions/4394 but I'd rather not deal with it if I can have the above questions answers. I'd be really happy if anyone could reply
GitHub
Database session + Credentials login · nextauthjs next-auth · Discu...
I am in need of help when it comes to logging in with credentails. i am trying to implement next-auth in my project and managed to make 3rd party auth (Google, Github) work. I implemented the Crede...
Hampterultimate
Hampterultimate•2y ago
I guess ill be the only one lonely enough to answer my own post T_T For anyone who is having the same issue as me, here is the answer. I dont know how I missed it. (Check the image) Here is another great resource https://stackoverflow.com/questions/43452896/authentication-jwt-usage-vs-session
Stack Overflow
Authentication: JWT usage vs session
What is the advantage of using JWTs over sessions in situations like authentication? Is it used as a standalone approach or is it used in the session?
kingfisher95
kingfisher95•2y ago
Did you get anywhere with this? I get that using the Credentials provider is a no support option but I really just want a basic username and password login, I don't get why it's so hard to do..
Hampterultimate
Hampterultimate•2y ago
Yes I did it. Well basically I lost some functionality. Those functionality was saving user session data in the database. I don't mind losing that functionality so I am fine with it. I also dropped the three extra tables created when initializing the project with NextAuth as they were not being used due to me using credentials provider. Here, to make your life easier I'll just give you the code
export const authOptions: NextAuthOptions = {
callbacks: {
jwt({ token, user }) {
/* User table contents is exposed in tokens */
if (user) {
token.id = user.id;
}
return token;
},
session({ session, token, user }) {
if (session.user) {
session.user.id = token.id as string;
// session.user.role = user.role; <-- put other properties on the session here
}
return session;
},
},
providers: [
CredentialsProvider({
// The name to display on the sign in form (e.g. 'Sign in with...')
name: "Email",
// The credentials is used to generate a suitable form on the sign in page.
// You can specify whatever fields you are expecting to be submitted.
// e.g. domain, username, password, 2FA token, etc.
// You can pass any HTML attribute to the <input> tag through the object.
credentials: {
email: {
label: "Email",
type: "email",
placeholder: "example@gmail.com",
},
password: { label: "Password", type: "password" },
},

export const authOptions: NextAuthOptions = {
callbacks: {
jwt({ token, user }) {
/* User table contents is exposed in tokens */
if (user) {
token.id = user.id;
}
return token;
},
session({ session, token, user }) {
if (session.user) {
session.user.id = token.id as string;
// session.user.role = user.role; <-- put other properties on the session here
}
return session;
},
},
providers: [
CredentialsProvider({
// The name to display on the sign in form (e.g. 'Sign in with...')
name: "Email",
// The credentials is used to generate a suitable form on the sign in page.
// You can specify whatever fields you are expecting to be submitted.
// e.g. domain, username, password, 2FA token, etc.
// You can pass any HTML attribute to the <input> tag through the object.
credentials: {
email: {
label: "Email",
type: "email",
placeholder: "example@gmail.com",
},
password: { label: "Password", type: "password" },
},

async authorize(credentials, req) {
// You need to provide your own logic here that takes the credentials
// submitted and returns either a object representing a user or value
// that is false/null if the credentials are invalid.
// e.g. return { id: 1, name: 'J Smith', email: 'jsmith@example.com' }
// You can also use the `req` object to obtain additional parameters
// (i.e., the request IP address)
const creds = await loginSchema.parseAsync(credentials);
const user = await prisma.user.findFirst({
where: { email: creds.email },
});

if (!user) {
return null;
}

if (user) {
console.log(user);
}

// Maybe add password hashing here
if (user.password !== creds.password) {
return null;
}

return {
...user,
};
},
}),
],

session: {
strategy: "jwt",
},
adapter: PrismaAdapter(prisma),
secret: process.env.NEXTAUTH_SECRET,
};
async authorize(credentials, req) {
// You need to provide your own logic here that takes the credentials
// submitted and returns either a object representing a user or value
// that is false/null if the credentials are invalid.
// e.g. return { id: 1, name: 'J Smith', email: 'jsmith@example.com' }
// You can also use the `req` object to obtain additional parameters
// (i.e., the request IP address)
const creds = await loginSchema.parseAsync(credentials);
const user = await prisma.user.findFirst({
where: { email: creds.email },
});

if (!user) {
return null;
}

if (user) {
console.log(user);
}

// Maybe add password hashing here
if (user.password !== creds.password) {
return null;
}

return {
...user,
};
},
}),
],

session: {
strategy: "jwt",
},
adapter: PrismaAdapter(prisma),
secret: process.env.NEXTAUTH_SECRET,
};
I had to split it up because of discord text limit. Just paste those two one by one and use prettier to auto indent. If you find any line hard to understand let me know. I think the only thing that might not be obvious is the type checking. I am using zod for loginSchema to parseAsync to check for input credentials. Oh also all of this is in auth.ts folder
kingfisher95
kingfisher95•2y ago
Yeah this code looked familiar, I've tried this and useSession always returns null so I can't do anything with it After some debugging the JWT and Session handler doesn't always get the user passed to it, and when it doesn't the Session handler encounters an error trying to read id from user, since user doesn't always get passed, it's sometimes undefined causing the error, the bigger problem is that this is a 100% fail rate in my setup. Those handlers DO get the user, but only when it doesn't matter. They are both called twice during sign in, the first time they get the user, everything is hunky dory, the second time they don't, then error, then no auth/user on the frontend Flow I've noticed, Authorize -> JWT -> JWT (undefined user) -> Session (undefined user) -> Error -> JWT (undefined user) -> Session (undefined user) -> Error
Hampterultimate
Hampterultimate•2y ago
Its weird, maybe you are doing something wrong in error handling because if you return null in the authOptions cred provider nothing should happen. Did you try out my code? Because there im going into authorize, returning the whole user data and sending it to the JWT, there I am just using JWT token and setting token.id to the received user.id. That should work with no issues. You can try debugging from authOptions and see if you are returning user data containing the id in it. And then go to JWT and see if it is receiving the id so it can set session token id for the browser.
kingfisher95
kingfisher95•2y ago
Yes I did try that code. I'm just going to switch to Lucia Auth instead, more boilerplate but at least I can have basic username&password without jumping through several loops and being told its not a good idea to use creds even though I don't see the harm in them..
Hampterultimate
Hampterultimate•2y ago
If it is working as you want then more power to you :D
kingfisher95
kingfisher95•2y ago
True, just didn't think I'd need to switch to a different auth library just to get what I want without the headache
Hampterultimate
Hampterultimate•2y ago
Does it create session tokens and all too like in NextAuth? Yeah they really want you to follow the passwordles sign in no matter what. Maybe I should have went with that instead. I wouldnt had to think about creating another functionality to reset password on forgetting
kingfisher95
kingfisher95•2y ago
Yeah that's what I hate but oh well.. There's a password somewhere along the line, would've been easier if it was done locally If by token you mean a cookie then yeah It does support oauth too so if you still need discord or GitHub or whatever other service as a login
Hampterultimate
Hampterultimate•2y ago
I see, thats better then x) I dont know the whole picture so I cant say for sure. I hope Theo doesnt get mad at me for that 😂
kingfisher95
kingfisher95•2y ago
From my limited use, I'd argue against swapping for now, there's stuff I'd like Lucia to change before I'd say it can be a good alternative Has Theo even mentioned credential logins at all ever?
Hampterultimate
Hampterultimate•2y ago
Hmmm the videos that ive seen from him, I have mostly seen him use other methods. I can't be sure though as I have not seen all of his videos.
kingfisher95
kingfisher95•2y ago
I'd say it would be nice to hear his thoughts on it but this thread isn't the place
Want results from more Discord servers?
Add your server