使用Node Passport和Google身份验证限制登录特定域名

18
我正在工作中的一个内部服务上实现Google身份验证。这是一个JS客户端重型应用程序,具有Node后端。我选择使用Passport.js节点模块和passport-google-oauth策略。
我已经成功地让它工作了,但仍有一件事令我困惑。我想确保我的应用程序仅允许公司员工登录。根据官方文档,我知道可以使用一个称为“hd”的参数限制域名以进行登录。
首先,在Passport.js的上下文中您在哪里发送该参数?我不明白代码中的位置。如果有帮助的话,我主要遵循passport-google-oauth提供的示例
其次,在理论上这一切是如何工作的?是在Google方面,他们拒绝任何试图从我们公司以外的域名访问应用程序的人。或者是在我的那一边,我需要检查用户从哪个域名登录?
2个回答

21

这是一个例子:

// first make sure you have access to the proper scope on your login route
app.get("/login", passport.authenticate("google", {
    scope: ["profile", "email"]
}));

// set up your Google OAuth strategy elsewhere...
passport.use(new GoogleStrategy({
    clientID: "something",
    clientSecret: "something",
    callbackURL: "/something"
}, function(token, refreshToken, profile, done){
    if(profile._json.hd === "yourdomain.com"){
        // find or create user in database, etc
        User.find({ id: profile.id }).done(done);
    }else{
        // fail        
        done(new Error("Invalid host domain"));
    }
});

为了更好的说明,这里提供了“profile”变量完整的变量转储。

{ 
    provider: 'google',
    id: '12345678987654321',
    displayName: 'Don Draper',
    name: { familyName: 'Whitman', givenName: 'Richard' },
    emails: [ { value: 'don@scdp.com' } ],
    _raw: 'a bunch of stringified json',
    _json: { 
        id: '123456789',
        email: 'something@something.com',
        verified_email: true,
        name: 'Don Draper',
        given_name: 'Don',
        family_name: 'Draper',
        link: 'https://plus.google.com/123456789',
        picture: 'https://lh3.googleusercontent.com/XdUIqdMkCWA/AAAAAAAAAAI/AAAAAAAAAAA/123456789/photo.jpg',
        gender: 'male',
        locale: 'en',
        hd: 'yourdomain.com' 
    } 
}

这里有一些详细的教程,应该可以回答你对所有这些理论的问题。你需要两者的结合。

  1. 本地认证和基本设置
  2. Google认证

10
profile._json.hd 现在似乎改为 profile._json.domain - JBCP

13

我建议采用两步方法。如果这样会使事情变得太复杂,我很乐意听取反馈意见。

1)帮助用户选择正确的账户

passport.authenticate('google', {
    // Only show accounts that match the hosted domain.
    hd: 'example.com',
    // Ensure the user can always select an account when sent to Google.
    prompt: 'select_account',
    scope: [
        'https://www.googleapis.com/auth/plus.login',
        'https://www.googleapis.com/auth/plus.profile.emails.read'
    ]
})(req, res, next);

2) 验证他们的个人资料

当用户被发送到accounts.google.com进行身份验证时,URL中有一个简单的hd=example.com查询参数。您可以删除它并使用任何帐户进行身份验证(Passport将成功验证选择的帐户域的Oauth代码),因此它应仅被视为最终用户的便利,而不是服务器的安全措施。

当Passport 解析身份验证时,只需像aembke的回答中那样检查托管的域即可:

passport.use(new google_strategy({
    clientID: ...
    clientSecret: ...
    callbackURL: ...
}, function(token, tokenSecret, profile, done) {

    if (profile._json.domain !== 'example.com') {
        done(new Error("Wrong domain!"));
    } else {
        done(null, profile);
    }

}));

1
谢谢Charlie!使用passport-google-oauth2,它对我有效。 - Ahmedskaya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接