title: Authentication through Passport.js with 3rd-party (discord) on React works locally but not when hosted on Heroku
body: <p>I've been trying to implement signin with discord using Passportjs and managed to get it to work locally (partially, I'm having problems dealing with the redirect after the callback, so for now I manually route myself back to the landing page @ "/"), successfully redirecting to <a href="https://discordapp.com/oauth2/authorize" rel="nofollow noreferrer">https://discordapp.com/oauth2/authorize</a>... and all. However when hosted on Heroku, it no longer works The address bar shows the correct "/auth/discord" address, but only a blank page shows up.</p>
  
  <p>I've tried using LinkContainers from react-router-bootstrap, playing with Nav.Item and Nav.Link from react-bootstrap, turned CORS on and off, rearranging the server-side route order, using just anchor tags, adjusting the scope of the authentication request and several other things that I can't recall now. Nothing seems to make a difference though. I must be barking up the wrong trees.</p>
  
  <p>Would greatly appreciate any hints as to what I should be looking at. Please find my code below:</p>
  
  <p><strong>App.js</strong></p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>import React, { useEffect } from "react";
  import { Switch, Route } from "react-router-dom";
  import { connect } from "react-redux";
  
  import { checkUserSession } from "./redux/user/user.actions";
  
  import Header from "./components/header/header.component";
  const Landing = () =&gt; &lt;h2&gt;Landing&lt;/h2&gt;;
  const FrontTest = () =&gt; &lt;h2&gt;FrontTest&lt;/h2&gt;;
  
  const App = ({ checkUserSession, currentUser }) =&gt; {
    useEffect(() =&gt; {
      checkUserSession();
    }, [checkUserSession]);
  
    return (
      &lt;div&gt;
        &lt;Header /&gt;
        &lt;Switch&gt;
          &lt;Route exact path="/" component={Landing} /&gt;
          &lt;Route exact path="/fronttest" component={FrontTest} /&gt;
        &lt;/Switch&gt;
      &lt;/div&gt;
    );
  };
  
  const mapStateToProps = ({ user: { currentUser } }) =&gt; ({
    currentUser,
  });
  
  const mapDispatchToProps = (dispatch) =&gt; ({
    checkUserSession: () =&gt; dispatch(checkUserSession()),
  });
  
  export default connect(mapStateToProps, mapDispatchToProps)(App);</code></pre>
  </div>
  </div>
  </p>
  
  <p><strong>header.component.jsx</strong>
  <div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>import React from "react";
  import { connect } from "react-redux";
  
  import Navbar from "react-bootstrap/Navbar";
  import Nav from "react-bootstrap/Nav";
  import Button from "react-bootstrap/Button";
  
  import DiscordSignin from "../discord-signin/discord-signin.component";
  
  import { signOutStart } from "../../redux/user/user.actions";
  
  const Header = ({ currentUser, signOutStart }) =&gt; (
    &lt;Navbar bg="dark" variant="dark" fixed="sticky-top" expand="sm"&gt;
      &lt;Navbar.Brand href="/"&gt;Race League&lt;/Navbar.Brand&gt;
      &lt;Navbar.Toggle aria-controls="basic-navbar-nav" /&gt;
      &lt;Navbar.Collapse id="basic-navbar-nav"&gt;
        &lt;Nav className="mr-auto"&gt;
          &lt;Nav.Link href="/fronttest"&gt;FrontTest&lt;/Nav.Link&gt;
        &lt;/Nav&gt;
        {currentUser ? (
          &lt;Button onClick={signOutStart} variant="outline-danger"&gt;
            Sign out
          &lt;/Button&gt;
        ) : (
          &lt;Nav.Link href="/auth/discord"&gt;
            &lt;DiscordSignin /&gt;
          &lt;/Nav.Link&gt;
        )}
      &lt;/Navbar.Collapse&gt;
    &lt;/Navbar&gt;
  );
  
  const mapStateToProps = ({ user: { currentUser } }) =&gt; ({
    currentUser,
  });
  
  const mapDispatchToProps = (dispatch) =&gt; ({
    signOutStart: () =&gt; dispatch(signOutStart()),
  });
  
  export default connect(mapStateToProps, mapDispatchToProps)(Header);</code></pre>
  </div>
  </div>
  </p>
  
  <p><strong>server.js</strong></p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>const express = require("express");
  const cors = require("cors");
  const bodyParser = require("body-parser");
  const cookieParser = require("cookie-parser");
  const path = require("path");
  const compression = require("compression");
  const enforce = require("express-sslify");
  
  const passport = require("passport");
  
  if (process.env.NODE_ENV !== "production") require("dotenv").config();
  
  require("./models/User");
  require("./services/passport");
  
  const app = express();
  const PORT = process.env.PORT || 5000;
  
  app.use(bodyParser.json());
  app.use(bodyParser.urlencoded({ extended: true }));
  app.use(cookieParser());
  
  app.use(cors());
  
  app.use(passport.initialize());
  
  require("./routes/authRoutes")(app);
  
  if (process.env.NODE_ENV === "production") {
    app.use(compression());
    app.use(enforce.HTTPS({ trustProtoHeader: true }));
    app.use(express.static(path.join(__dirname, "client/build")));
  
    app.get("*", (req, res) =&gt; {
      res.sendFile(path.join(__dirname, "client/build", "index.html"));
    });
  }
  
  app.listen(PORT, (error) =&gt; {
    if (error) throw error;
    console.log("Server running on port " + PORT);
  });</code></pre>
  </div>
  </div>
  </p>
  
  <p><strong>authRoutes.js</strong></p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>const passport = require("passport");
  const jwt = require("jsonwebtoken");
  
  module.exports = app =&gt; {
    app.get("/auth/discord", passport.authenticate("discord"));
  
    app.get("/auth/discord/callback", (req, res) =&gt; {
      passport.authenticate(
        "discord",
        {
          failureRedirect: "/",
          session: false
        },
        (error, user) =&gt; {
          if (error || !user) {
            res.status(400).json({ error });
          }
  
          // jwt content
          const payload = {
            ...user,
            expires: Date.now() + 30 * 24 * 60 * 60 * 1000
          };
  
          // assign payload to req.user
          req.login(payload, { session: false }, error =&gt; {
            if (error) {
              res.status(400).send({ error });
            }
  
            // generate a signed json web token and return it in the response
            const token = jwt.sign(JSON.stringify(payload), process.env.JWT_KEY);
            const cookieOption =
              process.env.NODE_ENV === "production" ? { secure: true } : {};
            // assign jwt to cookie
            res.cookie("jwt", token, cookieOption);
            res.redirect("/");
          });
        }
      )(req, res);
    });
  
    app.get(
      "/api/current_user",
      passport.authenticate("jwt", { session: false }),
      (req, res) =&gt; {
        const { user } = req;
        res.status(200).send({ user });
      }
    );
  };</code></pre>
  </div>
  </div>
  </p>