Home > OS >  Google OAuth 2.0 email missing from profile
Google OAuth 2.0 email missing from profile

Time:01-11

I am trying to set Google OAuth 2.0 via Passport. I am developping a node.js using express. Node.js : v18.12.1

When the user hasn't been created yet, I try to create it based on the info provided by Google. However, the email is missing for some reason.

Scope I am using on OAuth 2.0 :

enter image description here

Code extract of the problem :


passport.use(new googleAuth.Strategy({
        clientID: process.env.GOOGLE_CLIENT_ID!,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
        callbackURL: "http://localhost:3000/auth/google/secrets",
        scope: ["email","profile"]
    },
    (accessToken: string, refreshToken: string, profile: googleAuth.Profile, cb: VerifyCallback) => {
        User.findOne({googleId: profile.id}, (err: CallbackError, user: PassportLocalModel<IUser>) => {
            if(err){
                return cb(err);
            }else if(user){
                return cb(err, user);
            }else{
                const user = new User({
                    email: profile.emails![0].value,
                    googleId: profile.id,
                });

                user.save((err: CallbackError) => {
                    if(err){
                        console.log(err);
                        cb(err);
                    }
                })
            }
        })
       
    }
));

Profile.emails is undefined as well as _json.email (cf : https://developers.google.com/identity/openid-connect/openid-connect#an-id-tokens-payload)

Any idea why ?

Don't hesitate to ask if more info needed.

Thank you

EDIT :

Content of the _json (real content hidden) :

 _json: {
    sub: <somestring>,
    name: <some name>,
    given_name: <some name>,
    family_name: <some name>,
    picture: <some url>,
    locale: 'en-GB'
  }

CodePudding user response:

I found the solution to my problem.

Turn out I was overriding the scope options during authentication.

app.get("/auth/google", 
        passport.authenticate("google", {scope: ["profile"]})
);

By simply removing the option, the problem is fixed.

app.get("/auth/google", 
        passport.authenticate("google")
);

Solution

passport.use(new googleAuth.Strategy({
        clientID: process.env.GOOGLE_CLIENT_ID!,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
        callbackURL: "http://localhost:3000/auth/google/secrets",
        scope: ["profile", "email"]
    },
    (accessToken: string, refreshToken: string, profile: googleAuth.Profile, cb: VerifyCallback) => {
        User.findOne({googleId: profile.id}, (err: CallbackError, user: PassportLocalModel<IUser>) => {
            if(err){
                return cb(err);
            }else if(user){
                return cb(err, user);
            }else{
                const user = new User({
                    email: profile.emails![0].value,
                    googleId: profile.id,
                });

                user.save((err: CallbackError) => {
                    if(err){
                        console.log(err);
                        cb(err);
                    }
                })
            }
        })
       
    }
));

app.get("/auth/google", 
        passport.authenticate("google")
    );


CodePudding user response:

You could also remove the option on the google strategy and use on your auth route like this

 passport.use(new googleAuth.Strategy({
          clientID: process.env.GOOGLE_CLIENT_ID!,
          clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
          callbackURL: "http://localhost:3000/auth/google/secrets",
      },
      (accessToken: string, refreshToken: string, profile: googleAuth.Profile, cb: VerifyCallback) => {
           //...
      }
 ));

    app.get("/auth/google", 
        passport.authenticate("google", {scope: ["email", "profile"]})
);

As you can see at their documentation: https://www.passportjs.org/packages/passport-google-oauth20/

  • Related