@@ -124,6 +124,18 @@ const getVerifiedEmails = (githubEmails) =>
124124const getPrimaryEmail = ( githubEmails ) =>
125125 ( lodash . find ( githubEmails , { primary : true } ) || { } ) . value ;
126126
127+ /**
128+ * Get primary email from Google OAuth profile.
129+ * Returns the first email if available, or null if emails array is missing/empty.
130+ */
131+ const getGooglePrimaryEmail = ( googleEmails ) => {
132+ if ( ! Array . isArray ( googleEmails ) || googleEmails . length === 0 ) {
133+ return null ;
134+ }
135+ const primaryEmail = googleEmails [ 0 ] ?. value ?. trim ( ) ;
136+ return primaryEmail || null ;
137+ } ;
138+
127139/**
128140 * Sign in with GitHub.
129141 */
@@ -234,14 +246,24 @@ passport.use(
234246 {
235247 clientID : process . env . GOOGLE_ID ,
236248 clientSecret : process . env . GOOGLE_SECRET ,
237- callbackURL : 'https://editor.p5js.org /auth/google/callback' ,
249+ callbackURL : ` ${ process . env . EDITOR_URL } /auth/google/callback` ,
238250 passReqToCallback : true ,
239251 scope : [ 'openid email' ]
240252 } ,
241253 async ( req , accessToken , refreshToken , profile , done ) => {
242254 try {
255+ // Validate that emails array exists and has at least one element
256+ const primaryEmail = getGooglePrimaryEmail ( profile . _json ?. emails ) ;
257+ if ( ! primaryEmail ) {
258+ return done ( null , false , {
259+ msg :
260+ 'Unable to retrieve email from Google account. ' +
261+ 'Please ensure your Google account has an email address and try again.'
262+ } ) ;
263+ }
264+
243265 const existingUser = await User . findOne ( {
244- google : profile . _json . emails [ 0 ] . value
266+ google : primaryEmail
245267 } ) . exec ( ) ;
246268
247269 if ( existingUser ) {
@@ -258,18 +280,16 @@ passport.use(
258280 return done ( null , existingUser ) ;
259281 }
260282
261- const primaryEmail = profile . _json . emails [ 0 ] . value ;
262-
263283 if ( req . user ) {
264284 if ( ! req . user . google ) {
265- req . user . google = profile . _json . emails [ 0 ] . value ;
285+ req . user . google = primaryEmail ;
266286 req . user . tokens . push ( { kind : 'google' , accessToken } ) ;
267287 req . user . verified = User . EmailConfirmation ( ) . Verified ;
268288 }
269289 await req . user . save ( ) ;
270290 return done ( null , req . user ) ;
271291 }
272- let username = profile . _json . emails [ 0 ] . value . split ( '@' ) [ 0 ] ;
292+ let username = primaryEmail . split ( '@' ) [ 0 ] ;
273293 const existingEmailUser = await User . findByEmail ( primaryEmail ) ;
274294 const existingUsernameUser = await User . findByUsername ( username , {
275295 caseInsensitive : true
@@ -285,7 +305,7 @@ passport.use(
285305 return done ( null , false , { msg : accountSuspensionMessage } ) ;
286306 }
287307 existingEmailUser . email = existingEmailUser . email || primaryEmail ;
288- existingEmailUser . google = profile . _json . emails [ 0 ] . value ;
308+ existingEmailUser . google = primaryEmail ;
289309 existingEmailUser . username = existingEmailUser . username || username ;
290310 existingEmailUser . tokens . push ( {
291311 kind : 'google' ,
@@ -301,7 +321,7 @@ passport.use(
301321
302322 const user = new User ( ) ;
303323 user . email = primaryEmail ;
304- user . google = profile . _json . emails [ 0 ] . value ;
324+ user . google = primaryEmail ;
305325 user . username = username ;
306326 user . tokens . push ( { kind : 'google' , accessToken } ) ;
307327 user . name = profile . _json . displayName ;
0 commit comments