Google OAuth 2.0 邮箱缺失于个人资料

huangapple go评论68阅读模式
英文:

Google OAuth 2.0 email missing from profile

问题

我正在尝试通过Passport设置Google OAuth 2.0。我正在使用Express开发Node.js应用程序。
Node.js版本:v18.12.1

当用户尚未创建时,我尝试根据Google提供的信息创建用户。但是,出于某种原因,电子邮件丢失了。

我在OAuth 2.0上使用的范围:

Google OAuth 2.0 邮箱缺失于个人资料

问题的代码片段:

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和_json.email都未定义(参考:https://developers.google.com/identity/openid-connect/openid-connect#an-id-tokens-payload)

有任何想法吗?

如果需要更多信息,请不要犹豫提问。

谢谢

编辑:

_json的内容(实际内容已隐藏):

_json: {
    sub: <某个字符串>,
    name: <某个姓名>,
    given_name: <某个姓名>,
    family_name: <某个姓名>,
    picture: <某个网址>,
    locale: 'en-GB'
  }

<details>
<summary>英文:</summary>

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&#39;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][1]][1]


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) =&gt; {
                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&#39;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'
}



  [1]: https://i.stack.imgur.com/omjUB.png

</details>


# 答案1
**得分**: 0

我找到了解决我的问题的方法。

原来是在身份验证期间覆盖了范围选项。

通过简单地移除该选项,问题已解决。

## 解决方案 ##

```javascript
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")
);
英文:

I found the solution to my problem.

Turn out I was overriding the scope options during authentication.

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

By simply removing the option, the problem is fixed.

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

Solution

passport.use(new googleAuth.Strategy({
        clientID: process.env.GOOGLE_CLIENT_ID!,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
        callbackURL: &quot;http://localhost:3000/auth/google/secrets&quot;,
        scope: [&quot;profile&quot;, &quot;email&quot;]
    },
    (accessToken: string, refreshToken: string, profile: googleAuth.Profile, cb: VerifyCallback) =&gt; {
        User.findOne({googleId: profile.id}, (err: CallbackError, user: PassportLocalModel&lt;IUser&gt;) =&gt; {
            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) =&gt; {
                    if(err){
                        console.log(err);
                        cb(err);
                    }
                })
            }
        })
       
    }
));

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


答案2

得分: 0

你还可以在Google策略上移除选项,并像这样在身份验证路由中使用:

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"]})
);

如你所见,你可以在他们的文档中查看更多信息:https://www.passportjs.org/packages/passport-google-oauth20/

英文:

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: &quot;http://localhost:3000/auth/google/secrets&quot;,
      },
      (accessToken: string, refreshToken: string, profile: googleAuth.Profile, cb: VerifyCallback) =&gt; {
           //...
      }
 ));

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

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

huangapple
  • 本文由 发表于 2023年1月11日 07:07:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/75076761.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定