Implementing onboarding using next-auth
Unanswered
Siamese Crocodile posted this in #help-forum

Siamese CrocodileOP
I want the user to be redirected to /onboarding after they've signed up for the first time using socials (google or github). Next Auth is a little hard for me to integrate so I'd really love some help!
import GoogleProvider from "next-auth/providers/google";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { NextAuthOptions } from "next-auth";
import { db } from "./db";
export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(db),
session: {
strategy: "jwt",
},
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
],
};
this is my auth.ts
file's code43 Replies

Siamese CrocodileOP
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma"
}
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId String
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
hasOnboarded Boolean @default(false)
}
model VerificationToken {
identifier String
token String @unique
expires DateTime
@@unique([identifier, token])
}
this is my schema file that I just copied from the nextauth docsplease note that i've added another item called
hasOnboarded Boolean @default(false)
to the User model to check whether the user has onboarded or not.I want to set the hasOnboarded value to true if the use has onboarded and then redirect them to the homepage everytime they access the onboard page unless they're signing up for the first time
how do I implement this?
I'm not using credentials login

@Siamese Crocodile I want the user to be redirected to /onboarding after they've signed up for the first time using socials (google or github). Next Auth is a little hard for me to integrate so I'd really love some help!
import GoogleProvider from "next-auth/providers/google";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { NextAuthOptions } from "next-auth";
import { db } from "./db";
export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(db),
session: {
strategy: "jwt",
},
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
],
};
this is my ``auth.ts`` file's code

You can setup a page where users will be sent after they first sign up in your NextAuth config. It's called
newUser
. [Reference](https://next-auth.js.org/configuration/pages)
@ncls. You can setup a page where users will be sent after they first sign up in your NextAuth config. It's called `newUser`. [Reference](https://next-auth.js.org/configuration/pages)

Siamese CrocodileOP
I have an onboarding page already setup. It's endpoint is '/onboarding'. I also have a page setup for users to signin. I just don't know how to proceed.
currently I only want them to sign in with their socials


@Siamese Crocodile I have an onboarding page already setup. It's endpoint is '/onboarding'. I also have a page setup for users to signin. I just don't know how to proceed.

Define a
newUser
page in your NextAuth config. Check the reference I linked
@ncls. Define a `newUser` page in your NextAuth config. Check the reference I linked

Siamese CrocodileOP
my bad. one sec

NextAuth will automatically check if they already signed up before or not and if not, redirect them to the page you defined

@ncls. NextAuth will automatically check if they already signed up before or not and if not, redirect them to the page you defined

Siamese CrocodileOP
oh, so I don't need to add another query to the table such has "hasOnboarded", right?

Nope, you don't

Siamese CrocodileOP
got it
auth seems soo hard to setup and the nextauth docs seem like they arent updated for the app router and its a nightmare.

Not much has changed for use in the app router. I'm using app router as well and most things still apply

Siamese CrocodileOP
I scrapped many projects in the last 6 months because I got stuck with authentication which made me go back to the tutorial hell

Authentication with NextAuth is actually pretty easy once you understood how it works

Siamese CrocodileOP
I have another question
one sec
import { db } from '@/lib/db'
import { PrismaAdapter } from '@next-auth/prisma-adapter'
import { nanoid } from 'nanoid'
import { NextAuthOptions, getServerSession } from 'next-auth'
import GoogleProvider from 'next-auth/providers/google'
export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(db),
session: {
strategy: 'jwt',
},
pages: {
signIn: '/sign-in',
},
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
],
callbacks: {
async session({ token, session }) {
if (token) {
session.user.id = token.id
session.user.name = token.name
session.user.email = token.email
session.user.image = token.picture
session.user.username = token.username
}
return session
},
async jwt({ token, user }) {
const dbUser = await db.user.findFirst({
where: {
email: token.email,
},
})
if (!dbUser) {
token.id = user!.id
return token
}
if (!dbUser.username) {
await db.user.update({
where: {
id: dbUser.id,
},
data: {
username: nanoid(10),
},
})
}
return {
id: dbUser.id,
name: dbUser.name,
email: dbUser.email,
picture: dbUser.image,
username: dbUser.username,
}
},
redirect() {
return '/'
},
},
}
export const getAuthSession = () => getServerSession(authOptions)
this is the route.ts file i found on a github repo (Code with Antonio's Reddit clone tutorial)why exactly are we doing what we're doing in the callback functions?
for example, I'm trying to build a community platform for my university and i want the user to have data like their Fullname, their semester, their engineering branch, whether or not they're a student or a faculty member and all that stuff that they have to fill in on the onboarding page. Only then i want them to be able to see the dashboard (home) page

You are adding custom properties. By default, NextAuth will store 3 things in your session/token: email, name and image which are all coming from the OAuth provider the user used.
If you want to add custom properties from your database, like username, your own image, access roles (admin, moderator etc.), you add them inside the callback functions
If you want to add custom properties from your database, like username, your own image, access roles (admin, moderator etc.), you add them inside the callback functions

Siamese CrocodileOP
async session({ token, session }) {
if (token) {
session.user.id = token.id
session.user.name = token.name
session.user.email = token.email
session.user.image = token.picture
session.user.username = token.username
}
return session
},
in this function, where are the parameters token and session coming from? is token coming from the prisma schema?i don't understand why we're assigning each session's value to the token

@Siamese Crocodile async session({ token, session }) {
if (token) {
session.user.id = token.id
session.user.name = token.name
session.user.email = token.email
session.user.image = token.picture
session.user.username = token.username
}
return session
}, in this function, where are the parameters token and session coming from? is token coming from the prisma schema?

token
is the token NextAuth created on sign up and session
is the user session which you can get on the client side using the useSession
hook
Siamese CrocodileOP
understood

@Siamese Crocodile i don't understand why we're assigning each session's value to the token

Because on the client side you can not decrypt the token but you can use the session so everything you want to use on the client side has to be added to the session

Siamese CrocodileOP
so all the stuff on the left i.e, .id, . name, .email etc and stuff is coming from the prisma schema file, right?
and all the stuff on the right side are coming from the token that is created by nextauth?

Kind of
The token NextAuth creates only includes name, email and image. Everything else is added in the
jwt
callback from your database. You can then add those values into the session as well using the session
callback
@ncls. The token NextAuth creates only includes name, email and image. Everything else is added in the `jwt` callback from your database. You can then add those values into the session as well using the `session` callback

Siamese CrocodileOP
return {
id: dbUser.id,
name: dbUser.name,
email: dbUser.email,
picture: dbUser.image,
username: dbUser.username,
}
this return statement from the jwt callback function, right?
Yes, that will be your JWT payload

Siamese CrocodileOP
ohhh----

And that will be what your
token
variable will include in your session
callback
Siamese CrocodileOP
okay wow! thank you for that. now it kinda makes sense. the payload from jwt callback is assigned to our session which can then be used across our web app
redirect() {
return '/'
},
when I redirect a new user to /onboarding using the newUser object, which one takes precedence? will the newuser be redirected to '/' or '/onboarding'?
@Siamese Crocodile redirect() {
return '/'
}, when I redirect a new user to /onboarding using the newUser object, which one takes precedence? will the newuser be redirected to '/' or '/onboarding'?

I actually don't know for custom redirects. I suggest letting NextAuth handle the redirect on sign in

Siamese CrocodileOP
okay i made it work a little @ncls.
the user is successfully redirected to the onboarding page after authenticating