@@ -87,10 +87,12 @@ export const authOptions: AuthOptions = {
8787 } ,
8888 } ) ,
8989 ] ,
90+
9091 pages : {
9192 signIn : '/auth/signin' ,
9293 error : '/auth/error' ,
9394 } ,
95+
9496 callbacks : {
9597 async signIn ( { user, account } ) {
9698 // Skip if not Google sign in or if email is missing
@@ -105,18 +107,20 @@ export const authOptions: AuthOptions = {
105107
106108 await dbConnect ( )
107109
110+ const normalizedEmail = user . email . toLowerCase ( )
111+
108112 // Check if user already exists
109113 const existingUser = ( await User . findOne ( {
110- email :
111- typeof user . email === 'string' ? user . email . toLowerCase ( ) : undefined ,
114+ email : normalizedEmail ,
112115 } ) . select ( '+passwordSet +roles' ) ) as IUser | null
113116
117+ let dbUser : IUser | null = null
114118 let isNewUser = false
115119
116120 if ( existingUser ) {
117- // Update Google ID if needed
121+ dbUser = existingUser
122+
118123 if ( ! existingUser . googleId && user . id ) {
119- // Use findOneAndUpdate to ensure atomic update
120124 const updatedUser = await User . findOneAndUpdate (
121125 { email : existingUser . email } ,
122126 {
@@ -127,42 +131,45 @@ export const authOptions: AuthOptions = {
127131 } ,
128132 } ,
129133 { new : true , runValidators : true }
130- )
134+ ) . select ( '+passwordSet +roles' )
131135
132- // Ensure we have the latest user data with roles
133136 if ( updatedUser ) {
134- user . roles = updatedUser . roles
137+ dbUser = updatedUser
135138 }
136- } else {
137- // If user already has Google ID, ensure roles are passed
138- user . roles = existingUser . roles
139139 }
140- // If user exists and has a password set, allow sign in
141- if ( existingUser . passwordSet ) {
142- return true
143- }
144- } else if ( user . email ) {
145- // Create new user from Google auth
146- await User . create ( {
140+
141+ } else {
142+ dbUser = await User . create ( {
147143 name : user . name ,
148- email : user . email ,
149- image : user . image || undefined , // Convert null to undefined
144+ email : normalizedEmail ,
145+ image : user . image || undefined ,
150146 googleId : user . id ,
151147 passwordSet : false ,
152- emailVerified : true , // Google OAuth automatically verifies email
153- roles : [ 'user' ] , // Default role for new users
148+ emailVerified : true ,
149+ roles : [ 'user' ] ,
154150 } )
155151 isNewUser = true
156152 }
157153
158- // Only redirect to set-password for new users or existing users without a password
159- if ( isNewUser || ( existingUser && ! existingUser . passwordSet ) ) {
160- const email = user . email || ''
161- return `/auth/set-password?email=${ encodeURIComponent ( email ) } ${ isNewUser ? '&new=true' : '' } `
154+ if ( dbUser && dbUser . _id ) {
155+ const mutableUser = user as {
156+ id ?: string
157+ roles ?: string [ ]
158+ }
159+
160+ mutableUser . id = dbUser . _id . toString ( )
161+ mutableUser . roles = dbUser . roles
162+ }
163+
164+ if ( isNewUser || ( dbUser && ! dbUser . passwordSet ) ) {
165+ return `/auth/set-password?email=${ encodeURIComponent ( normalizedEmail ) } ${
166+ isNewUser ? '&new=true' : ''
167+ } `
162168 }
163169
164170 return true
165171 } ,
172+
166173 async session ( { session, token } ) {
167174 if ( token . sub && session . user ) {
168175 session . user . id = token . sub
@@ -173,6 +180,7 @@ export const authOptions: AuthOptions = {
173180 }
174181 return session
175182 } ,
183+
176184 async jwt ( { token, user } ) {
177185 if ( user ) {
178186 token . sub = user . id
@@ -182,13 +190,16 @@ export const authOptions: AuthOptions = {
182190 return token
183191 } ,
184192 } ,
193+
185194 session : {
186195 strategy : 'jwt' ,
187- maxAge : 24 * 60 * 60 , // 24 hours
188- updateAge : 60 * 60 , // 1 hour
196+ maxAge : 24 * 60 * 60 ,
197+ updateAge : 60 * 60 ,
189198 } ,
199+
190200 jwt : {
191- maxAge : 24 * 60 * 60 , // 24 hours
201+ maxAge : 24 * 60 * 60 ,
192202 } ,
203+
193204 secret : process . env . NEXTAUTH_SECRET ,
194205}
0 commit comments