Click here to Skip to main content
15,887,350 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Trying to do LinkedIn Authorization Code Flow (3-legged OAuth) but I keep getting this error 'Unable to retrieve access token: appid/redirect uri/code verifier does not match authorization code. Or authorization code expired. Or external member binding exists' and I tested it on postman with the same params and it worked fine but it won't work in my app I don't know what I am doing wrong

I am using passportjs and I did the first step which is To request an authorization code, you must direct the member's browser to LinkedIn's OAuth 2.0 authorization page, where the member either accepts or denies your application's permission request. and that's working I get back the code that I need but then inside the try catch the post request is not working even tho all the params are correct

Java
const passport = require("passport");
const User = require("../models/User");
const LinkedInStrategy = require("passport-linkedin-oauth2").Strategy;
const axios = require("axios");
//const request = require("request"); //deprecated

const callbackURL = `${process.env.FRONTEND_URL}/`;

const authenticate = (req, res, next) => {
  passport.use(
    new LinkedInStrategy(
      {
        clientID: process.env.LINKEDIN_CLIENT_ID,
        clientSecret: process.env.LINKEDIN_CLIENT_SECRET,
        callbackURL: `${process.env.SERVER_URL}/api/v1/auth/linkedin/callback`,
        profileFields: ["id", "displayName", "email", "picture.type(large)"],
        passReqToCallback: true,
        state: true,
        scope: ["r_liteprofile", "r_emailaddress"],
      },
      async (req, accessToken, refreshToken, profile, done) => {
        await axios.get(`https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=${process.env.LINKEDIN_CLIENT_ID}&redirect_uri=${callbackURL}=r_liteprofile%20r_emailaddress`);
        const { code } = req.query;
        console.log("this is code", code);
        
      
        try { // where error is
          
          const tokenResponse = await axios.post(
            "https://www.linkedin.com/oauth/v2/accessToken",
            null,
            {
              params: {
                grant_type: "authorization_code",
                code: code,
                client_id: process.env.LINKEDIN_CLIENT_ID,
                client_secret: process.env.LINKEDIN_CLIENT_SECRET,
                redirect_uri: `${process.env.SERVER_URL}/api/v1/auth/linkedin/callback`,
              },
              headers: {
                "Content-Type": "application/x-www-form-urlencoded",
              },
            }
            
          );
         
          
          const accessToken = tokenResponse.data.access_token;
          console.log("this is new access token", accessToken);
      
          const profileResponse = await axios.get(
            "https://api.linkedin.com/v2/me",
            {
              headers: {
                Authorization: `Bearer ${accessToken}`,
              },
            }
          );
      
          const userProfile = profileResponse.data;
      
          console.log("User Profile:", userProfile);
      
          return tokenResponse.data.access_token;
        } catch (error) {
          console.error("Access Token Error:", error.message);
          done(error);
        }
        //console.log("accessToken", accessToken, "profile", profile);
        
        
      }
    )
  );
 
  passport.authenticate("linkedin",{
    session: false,
  })(req, res, next);
};



const callback = async (req, res) => {
 
/*********/ 
  passport.authenticate(
    "linkedin",
    {
      failureRedirect: `${process.env.FRONTEND_URL}/channels?login=error&provider=linkedin`,
      session: false,
    },
    function (err, page, info) {
      console.log("err", err);
      console.log("page", page);
      console.log("info", info);
      if (err) {
        res.redirect(
          `${process.env.FRONTEND_URL}/channels?login=error&provider=linkedin`
        );
      }
      if (page) {
        /**********  send page access token and page ID **********/
        // page access token expiry is the same as user access token expiry
        // as the long-lived token is used to fetch page token, it is 60 days

        const expiryInMilliSecond = 1000 * 60 * 60 * 24 * 60;
        const timestamp = Date.now() + expiryInMilliSecond; // 60 days from now
        res
          .cookie("LinkedinPageAccessToken", page.linkedinUser.accessToken, {
            httpOnly: true,
            secure: true,
            maxAge: expiryInMilliSecond,
          })
          .set("Access-Control-Allow-Credentials", "true");
        res.cookie("LinkedinPageId", page.linkedinUser.id, {
          maxAge: expiryInMilliSecond,
        }); // regular cookie: not confidential
        res.cookie("LinkedinExpiry", timestamp, {
          maxAge: expiryInMilliSecond,
        }); // regular cookie: not confidential
        res.redirect(
          // in order to show login status on the client side
          // pass login status, provider name to the client
          //`${process.env.FRONTEND_URL}/publishing`
          `${process.env.FRONTEND_URL}/channels?login=success&provider=linkedin`
        );
      } else {
        console.log("Linkedin auth failed");

        res.redirect(
          // `${process.env.FRONTEND_URL}/channels`
          `${process.env.FRONTEND_URL}/channels?login=error&provider=linkedin`
        );
      }
    }
  )(req, res);
};

module.exports = { authenticate, callback };


What I have tried:

I made sure all my params are correct but its still not working
Posted
Updated 15-Jul-23 22:19pm
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900