如何使用 Passport.js 对 Google API 进行后续的、经过身份验证的调用

How to make subsequent, authenticated calls to Google API using Passport.js

我正在尝试使用 Google API 对 Passport.js 用户进行身份验证和授权。我有 G Suite,我的所有用户都是 G Suite 组织的一部分。我在 G Suite 中设置了一系列角色以用于我的自定义应用程序。

身份验证部分没有问题并且按预期工作。问题是我需要使用登录用户的 userKeyhttps://www.googleapis.com/admin/directory/v1/customer/customer/roleassignments 进行后续调用,以获取该用户拥有的所有分配,我不确定什么是最好的方法这样做。

这是我的 /login 路线的相关部分现在的样子:

passport.use(
  new GoogleStrategy({
    clientID: process.env.GOOGLE_CLIENT_ID,
    clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    callbackURL: process.env.BASE_URL + '/login/google/callback'
  },
  function (accessToken, refreshToken, profile, done) {
    return done(null, profile)
  })
)

router.get('/', function (req, res, next) {
  // Render the login button
})

router.get('/google',
  passport.authenticate('google', {
    scope: [
      'email',
      'https://www.googleapis.com/auth/userinfo.profile',
      'https://www.googleapis.com/auth/admin.directory.rolemanagement.readonly'
    ]
  })
)

router.get('/google/callback', function (req, res, next) {
  passport.authenticate('google', function (err, user, info) {
    if (err) { return next(err) }
    if (!user) { return res.redirect('/login?error=no_user') }

    req.login(user, function (err) {
      if (err) { return next(err) }

      const accessToken = req.user.accessToken
      // Maybe do something here?

      return res.redirect('/')
    })
  })(req, res, next)
})

我可以在获取 accessToken 时将其存储到用户会话中,然后使用令牌作为不记名令牌进行回调,这可能工作正常,但这真的是它应该工作的方式吗? Passport.js 是否提供某种机制来简化后续的经过身份验证的调用?

经过进一步调查,如果您在初始身份验证后需要执行其他步骤,我认为您应该修改 Strategy 回调。

因此,要在 G Suite Admin 中设置自定义用户角色,您可以使用外部 request 库这样做:

import request from 'request'

passport.use(
  new GoogleStrategy({
    clientID: process.env.GOOGLE_CLIENT_ID,
    clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    callbackURL: process.env.BASE_URL + '/login/google/callback'
  },
  function (accessToken, refreshToken, profile, done) {
    const url = 'https://www.googleapis.com/admin/directory/v1/customer/' +
      process.env.GOOGLE_CUSTOMER_ID +
      '/roleassignments' +
      '?userKey=' +
      profile.id

    request.get(url, {
      auth: {
        bearer: accessToken
      }
    }, (error, response, body) => {
      if (error) {
        console.error(error)
        return done(null, false, { message: 'Could not authenticate.' })
      }
      const items = JSON.parse(response.body).items
      let role = null
      const roles = items.map((value) => {
        return value.roleId
      })

      if (roles.includes(process.env.GOOGLE_ROLE_ID_ADMIN)) {
        role = 'ADMIN'
      } else if (roles.includes(process.env.GOOGLE_ROLE_ID_OTHER)) {
        role = 'OTHER'
      } else {
        return done(null, false, { message: 'No valid user role' })
      }

      console.log('User role is ' + role)
      profile.role = role
      return done(null, profile)
    })
  })
)

如果您将获得的角色分配给 profile,您以后可以使用 req.user.role 轻松访问它。