0
const express = require("express");
const router = express.Router();
const axios = require("axios");
const querystring = require("querystring");
const dotenv = require("dotenv");
const session = require("express-session");
const MemoryStore = require("memorystore")(session);

dotenv.config();

const client_id = "27905";
const client_secret = "NEVER SHARE THIS!!!REMOVED";
const redirect_uri = `${process.env.SERVER_URL}/stackoverflow/callback`;

const sessionConfig = {
  secret: "your_secret_key", // Change this to a strong, unique secret
  resave: false,
  saveUninitialized: true,
  store: new MemoryStore({
    checkPeriod: 86400000, // prune expired entries every 24h
  }),
  cookie: {
    maxAge: 86400000, // 24 hours
  },
};

router.use(session(sessionConfig));

function generateRandomString(length) {
  const charset =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  let result = "";
  for (let i = 0; i < length; i++) {
    const randomIndex = Math.floor(Math.random() * charset.length);
    result += charset.charAt(randomIndex);
  }
  return result;
}

router.get("/login", (req, res) => {
  try {
    const state = generateRandomString(16);
    const scopes = "read_inbox write_access";

    // Save state in the session to validate it later in the callback
    req.session.linkedinState = state;

    res.redirect(
      "https://stackoverflow.com/oauth?" +
        querystring.stringify({
          client_id: client_id,
          scope: scopes,
          redirect_uri: redirect_uri,
          state: state,
        })
    );
  } catch (err) {
    console.log("Server error");
    console.error(err);
    res.status(500).json({
      success: false,
      message: "Server error",
    });
  }
});

router.get("/callback", async (req, res) => {
  try {
    const code = req.query.code || null;
    const state = req.query.state || null;
    const storedState = req.session.linkedinState;

    // Validate state to prevent CSRF attacks
    if (state === null || state !== storedState) {
      return res.status(403).json({
        success: false,
        message: "Invalid state parameter",
      });
    }

    // Clear the state from the session
    delete req.session.linkedinState;

    // Exchange the authorization code for an access token
    const tokenResponse = await axios.post(
      "https://stackoverflow.com/oauth/access_token",
      querystring.stringify({
        client_id: client_id,
        client_secret: client_secret,
        code: code,
        redirect_uri: redirect_uri,
      }),
      {
        headers: {
          "Content-Type": "application/x-www-form-urlencoded",
        },
      }
    );

    const accessToken = tokenResponse.data;

    // Store the access token securely (e.g., in the session)
    req.session.stackOverflowAccessToken = accessToken;

    // Redirect or perform any other action after successful authentication
    res.redirect(`http://localhost:3000/?${accessToken}`); 
  } catch (err) {
    console.log("Server error at callback");
    console.error(err);
    res.status(500).json({
      success: false,
      message: "Server error at callback",
    });
  }
});


module.exports = router;
1
  • You have leaked your client-secret. You should regenerate it.
    – rene
    Commented Dec 9, 2023 at 18:00

0

Browse other questions tagged .