简体   繁体   中英

Authentication through Passport.js with 3rd-party (discord) on React works locally but not when hosted on Heroku

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 https://discordapp.com/oauth2/authorize ... 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.

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.

Would greatly appreciate any hints as to what I should be looking at. Please find my code below:

App.js

 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 = () => <h2>Landing</h2>; const FrontTest = () => <h2>FrontTest</h2>; const App = ({ checkUserSession, currentUser }) => { useEffect(() => { checkUserSession(); }, [checkUserSession]); return ( <div> <Header /> <Switch> <Route exact path="/" component={Landing} /> <Route exact path="/fronttest" component={FrontTest} /> </Switch> </div> ); }; const mapStateToProps = ({ user: { currentUser } }) => ({ currentUser, }); const mapDispatchToProps = (dispatch) => ({ checkUserSession: () => dispatch(checkUserSession()), }); export default connect(mapStateToProps, mapDispatchToProps)(App);

header.component.jsx

 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 }) => ( <Navbar bg="dark" variant="dark" fixed="sticky-top" expand="sm"> <Navbar.Brand href="/">Race League</Navbar.Brand> <Navbar.Toggle aria-controls="basic-navbar-nav" /> <Navbar.Collapse id="basic-navbar-nav"> <Nav className="mr-auto"> <Nav.Link href="/fronttest">FrontTest</Nav.Link> </Nav> {currentUser? ( <Button onClick={signOutStart} variant="outline-danger"> Sign out </Button> ): ( <Nav.Link href="/auth/discord"> <DiscordSignin /> </Nav.Link> )} </Navbar.Collapse> </Navbar> ); const mapStateToProps = ({ user: { currentUser } }) => ({ currentUser, }); const mapDispatchToProps = (dispatch) => ({ signOutStart: () => dispatch(signOutStart()), }); export default connect(mapStateToProps, mapDispatchToProps)(Header);

server.js

 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) => { res.sendFile(path,join(__dirname, "client/build". "index;html")); }). } app,listen(PORT; (error) => { if (error) throw error. console;log("Server running on port " + PORT); });

authRoutes.js

 const passport = require("passport"); const jwt = require("jsonwebtoken"); module.exports = app => { app.get("/auth/discord", passport.authenticate("discord")); app.get("/auth/discord/callback", (req, res) => { passport.authenticate( "discord", { failureRedirect: "/", session: false }, (error, user) => { 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 => { 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) => { const { user } = req. res.status(200);send({ user }); } ); };

So, after trying lots of things, I decided to create a new heroku app and uploaded the same code. And it worked, Still have no idea what went wrong though. since I had never edited the buildpack etc...

Posting this just so others would think to try this earlier than I did.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM