Linkedin 策略回调无法使用

问题描述 投票:0回答:1

之前,我遵循来自 https://www.passportjs.org/packages/passport-linkedin-oauth2/ 的用于 linkedin 身份验证的 passort 官方文档,但我面临的问题是,放置在 LinkedIn 策略回调中的任何控制台都不是显示,但我无法在此回调中找到

accessToken, refreshToken, profile, done
的值。不过我尝试了另一种解决方案。我在回调控制器(不是策略回调)中手动添加了 api 请求,从中提取了用户信息,然后将其用于我的数据库操作。

passport.use(
  new LinkedInStrategy(
    {
      clientID: process.env.LINKEDIN_CLIENT_ID,
      clientSecret: process.env.LINKEDIN_CLIENT_SECRET,
      callbackURL: 'https://analyser-node.octalooptechnologies.com/auth/linkedin/callback',
      scope: [ 'email', 'openid', 'profile'],
      passReqToCallback: true,
    },
    async (accessToken, refreshToken, profile, done) => {
      try {
        console.log('Access Token:', accessToken);
        console.log('Profile Object:', profile);
        let user = await User.findOne({ linkedinId: profile.id });

        if (user) {
          return done(null, user);
        }

        user = await User.findOne({ email: profile.emails[0].value });
        if (user) {
          if (!user.linkedinId) {
            user.linkedinId = profile.id;
            user.verify = true;
            await user.save();
          }
          console.log('user in strategy:', user);
          
          return done(null, user);
        }

        const newUser = new User({
          linkedinId: profile.id,
          email: profile.emails[0].value,
          verify: true,
        });
        await newUser.save();
        done(null, newUser);
      } catch (error) {
        console.log('error in strategy:', error);
        done(error, null);
      }
    }
  )
);

passport.serializeUser((user, done) => {
  console.log('user in passport serializer:', user);
  done(null, user.id);
});

passport.deserializeUser(async (id, done) => {
  try {
    const user = await User.findById(id);
    done(null, user);
  } catch (error) {
    done(error, null);
  }
});

exports.linkedinAuth = passport.authenticate('linkedin', { state: true, scope: [ 'email', 'openid', 'profile']});

exports.linkedinAuthCallback = async(req, res) => {
  try {
   //step 1 : here we get this code from passport linkedin strategy.
    const code = req.query.code;
    // console.log("code:", code);
  
    const redirect_uri = "https://analyser-node.octalooptechnologies.com/auth/linkedin/callback";
    const client_id = process.env.LINKEDIN_CLIENT_ID
    const client_secret = process.env.LINKEDIN_CLIENT_SECRET

    var access_token;
    //step 2 : access token retrieval
    const access_token_url = `https://www.linkedin.com/oauth/v2/accessToken?grant_type=authorization_code&code=${code}&redirect_uri=${redirect_uri}&client_id=${client_id}&client_secret=${client_secret}`;
    const res_token = await axios.post(access_token_url)
    .then((res) => {
    access_token = res.data.access_token;
    })
    .catch((err) => {
    console.log(err);
    });
    console.log("access_token:", access_token);

    const user_info_url = `https://api.linkedin.com/v2/userinfo`;
  if (access_token) {
   const res_user_info = await axios
    .get(user_info_url, {
     headers: {
      Authorization: `Bearer ${access_token}`,
     },
    })
    .then((response) => {
     user_info = response.data;
     console.log('user_info:', user_info);

      const dbOperations = async () => {
        try {
          let userLinkedinId = await User.findOne({ linkedinId: user_info.sub });
          let userEmail = await User.findOne({ email: user_info.email });
          const userId = userEmail?._id
          if (userLinkedinId && userEmail) {
            // 1) if linkedinId exists in database
            // console.log('userEmail:', userEmail);
            // console.log('userLinkedinId:', userLinkedinId);
            try {
              const token = jwt.sign({ userId: userId, email: user_info.email }, secretKey, { expiresIn: '1h' });
              console.log('token_1:', token);
              
              const redirectUrl = `https://cv-analyzer-git-staging-octalooptechnologies-projects.vercel.app/recommendation?token=${token}&userId=${userId}`;
              res.redirect(redirectUrl);
            } catch (jwtError) {
              console.error('JWT generation error:', jwtError);
              res.status(500).json({ message: 'Internal server error during JWT generation' });
            }
          } else if (userEmail && !userLinkedinId) {
              // 2) if only email exists in database
              // console.log('userEmail:', userEmail);
              // console.log('userLinkedinId:', userLinkedinId);

              const updatedUser = await User.findOneAndUpdate(
                {email: user_info.email },  // Find by user ID
                { $set: { linkedinId: user_info.sub } },  // Add the new attribute
                { new: true }  // Optionally return the updated document
              );
              console.log('Updated user:', updatedUser);
            try {
              const token = jwt.sign({ userId: userId, email: user_info.email }, secretKey, { expiresIn: '1h' });
              console.log('token_2:', token);
              
              const redirectUrl = `https://cv-analyzer-git-staging-octalooptechnologies-projects.vercel.app/recommendation?token=${token}&userId=${userId}`;
              res.redirect(redirectUrl);
            } catch (jwtError) {
              console.error('JWT generation error:', jwtError);
              res.status(500).json({ message: 'Internal server error during JWT generation' });
            }
          } else if (!userEmail && !userLinkedinId) {
            // 3) if neither email nor linkedinId exists in database
            // console.log('userEmail:', userEmail);
            // console.log('userLinkedinId:', userLinkedinId);
            // console.log('newUser is about to be generated');
                    
            const newUser = new User({
              linkedinId: user_info.sub,
              email: user_info.email,
              verify: true,
              profileImage: user_info.picture
            });
            console.log('newUser:', newUser);

            const savedNewUser = await newUser.save();
            console.log('savedNewUser:', savedNewUser);
            const userId = savedNewUser._id
            
            try {
              const token = jwt.sign({ userId: userId, email: user_info.email }, secretKey, { expiresIn: '1h' });
              console.log('token_3:', token);
              
              const redirectUrl = `https://cv-analyzer-git-staging-octalooptechnologies-projects.vercel.app/recommendation?token=${token}&userId=${userId}`;
              res.redirect(redirectUrl);
            } catch (jwtError) {
              console.error('JWT generation error:', jwtError);
              res.status(500).json({ message: 'Internal server error during JWT generation' });
            }
          }

          
        } catch (error) {
          console.log('error:', error);
        }
      }
      dbOperations()
    })
    .catch((err) => {
     console.log("ERROR: ", err);
    });
  } else {
    console.log("access_token not found");
  }
  } catch (error) {
    console.log('internal error:', error);
    
    res.status(500).json({
     message: "Internal Server Error",
     error,
    })}
}

现在,我很困惑这是标准做法还是这些 api 调用应该自动触发?我无法看到放置在 linkedin 策略回调函数中的控制台。

node.js oauth-2.0 oauth linkedin-api
1个回答
-1
投票

请尝试以下代码,修复包括:

  1. 有效的 API 范围

  2. 数据库查询得到改进

  3. 删除多余的代币交换逻辑

  4. 修改了 Passport 的内置回调流程。

      passport.use(
      new LinkedInStrategy(
        {
          clientID: process.env.LINKEDIN_CLIENT_ID,
          clientSecret: process.env.LINKEDIN_CLIENT_SECRET,
          callbackURL: 'https://analyser-node.octalooptechnologies.com/auth/linkedin/callback',
          scope: ['r_emailaddress', 'r_liteprofile'],
          passReqToCallback: true,
        },
        async (req, accessToken, refreshToken, profile, done) => {
          try {
            console.log('Access Token:', accessToken);
            console.log('Profile Object:', profile);
    
            let user = await User.findOne({ linkedinId: profile.id }) || await User.findOne({ email: profile.emails[0].value });
            if (!user) {
              user = new User({
                linkedinId: profile.id,
                email: profile.emails[0].value,
                verify: true,
              });
              await user.save();
            }
            done(null, user);
          } catch (error) {
            console.error('Error in LinkedIn strategy:', error);
            done(error, null);
          }
        }
      )
    );
    
    

回拨路线:

app.get('/auth/linkedin/callback',
  passport.authenticate('linkedin', { failureRedirect: '/login' }),
  (req, res) => {
    const token = jwt.sign({ userId: req.user.id, email: req.user.email }, secretKey, { expiresIn: '1h' });
    const redirectUrl = `https://cv-analyzer.vercel.app/recommendation?token=${token}&userId=${req.user.id}`;
    res.redirect(redirectUrl);
  }
);

希望这有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.