如何在同一个应用程序中两次使用 passport-google-oauth20

how to use passport-google-oauth20 twice in the same app

我试图在我的节点应用程序中使用 passport-google-oauth20 两次,但它不起作用。还在学习护照认证。

问题来了:

我制作了一个用户使用 google(/auth.google) 登录的按钮和一个用户使用 google(/users/google) 注册的按钮。我想要它,以便如果用户已经使用 google 在我的应用程序上注册并且他继续按下“使用 google 注册”按钮,他应该被重定向回注册页面(身份验证失败) .在我的例子中,当我添加一次策略并仅添加一个登录按钮(不注册)时,身份验证有效并且用户被重定向到仪表板。但是,当我在 passport.js 中再次添加策略并且“已注册用户”尝试使用 google 登录时,他被重定向到注册页面(找到使用 google 按钮注册的页面) 而不是仪表板。我知道没有必要做这样的事情,也不需要再次使用相同的 strat 进行注册,因为它对登录的工作方式相同。只是想知道是否可以工作。

这是我的代码:

Passport.js

const GoogleStrategy = require("passport-google-oauth20").Strategy;

const myClientId = require("./keys").clientID;
const myClientSecret = require("./keys").clientSecret;

// get the user schema
const User = require("../models/User");

// passport google authentication
module.exports = function (passport) {
  passport.use(
    new GoogleStrategy(
      {
        clientID: myClientId,
        clientSecret: myClientSecret,
        callbackURL: "/auth/google/callback",
      },
      (accessToken, refreshToken, profile, done) => {
        const newUser = new User({
          googleId: profile.id,
          displayName: profile.displayName,
          firstName: profile.name.givenName,
          lastName: profile.name.familyName,
          image: profile.photos[0].value,
        });

        User.findOne({ googleId: profile.id })
          .then((user) => {
            if (user) {
              done(null, user);
            } else {
              newUser.save().then((userd) => {
                done(null, userd);
              });
            }
          })
          .catch((err) => console.log(err));
      }
    )
  );

// using same strategy again but different callback URL

  passport.use(
    new GoogleStrategy(
      {
        clientID: myClientId,
        clientSecret: myClientSecret,
        callbackURL: "/users/google/callback",
      },
      (accessToken, refreshToken, profile, done) => {
        const newUser = new User({
          googleId: profile.id,
          displayName: profile.displayName,
          firstName: profile.name.givenName,
          lastName: profile.name.familyName,
          image: profile.photos[0].value,
        });

        User.findOne({ googleId: profile.id })
          .then((user) => {
            if (user) {
              done(null, false);
            } else {
              newUser.save().then((userd) => {
                done(null, userd);
              });
            }
          })
          .catch((err) => console.log(err));
      }
    )
  );

  passport.serializeUser((user, done) => {
    done(null, user.id);
  });

  passport.deserializeUser((id, done) => {
    User.findById(id, (err, user) => {
      done(err, user);
    });
  });
};

app.js

/* initalized passport, session and other stuff here but just showing you the routes and the passport 
function in app.js */

require("./config/passport")(passport);

app.use("/auth", require("./routes/auth"));
app.use("/users", require("./routes/users"));

auth.js

const express = require("express");
const passport = require("passport");
const router = express.Router();

//? register and login handle
router.get(
  "/google",
  passport.authenticate("google", {
    scope: ["profile"],
  })
);

//? google auth callback
router.get(
  "/google/callback",
  passport.authenticate("google", {
    successRedirect: "/dashboard",
    failureRedirect: "/",
  })
);

module.exports = router;

users.js

const express = require("express");
const router = express.Router();
const passport = require("passport");
const { ensureAuthenticated, forwardAuth } = require("../config/checkAuth");

//? register page
router.get("/register", forwardAuth, (req, res) => {
  res.render("register");
});

//? login page
router.get("/login", forwardAuth, (req, res) => {
  res.render("login");
});

//? logout handle
router.get("/logout", (req, res) => {
  req.logOut();
  res.redirect("/");
});

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

router.get(
  "/google/callback",
  passport.authenticate("google", {
    successRedirect: "/dashboard",
    failureRedirect: "/users/register",
  })
);

module.exports = router;

因此,如果用户在 /auth/google 上登录...他将被重定向到注册页面 (/users/register)!不知道为什么

我解决了我的问题。

解决方法其实很简单。只使用相同的 passport.js 文件。

在passport.js

const GoogleStrategy = require("passport-google-oauth20").Strategy;

module.exports = function (passport) {

  passport.use("firstUse", new GoogleStrategy(....))
  passport.use("secondUse", new GoogleStrategy(...))
}

所以问题是你可以用任何你想要的名字注册策略,然后当你想在路由中处理授权中间件时,你只需这样做:

用户和 auth.js

app.get("/auth/google/callback", passport.authenticate("firstUse"));
app.get("/users/google/callback", passport.authenticate("secondUse"));

只需添加您注册时使用的名称。我认为有必要只使用 passport.authenticate("google") 而不是除 "google" 以外的任何名称。