Discord OAuth2 Freezing - node.js

I'm developing a website with Node.js and express. I want to have an option to sign in with Discord.
I've followed the guide on the npm page as well as a video guide
I can access the Discord OAuth page but when I click "Authorize" it will log my discord ID on the console but it will not redirect(supposed to redirect to /auth/success). If I click "cancel" it will immediately redirect to /auth/forbidden, as intended. There are no errors.
app.js
const express = require('express');
const http = require('http');
const session = require('express-session');
const passport = require('passport');
const discordStrategy = require('./strategies/discordstrategy');
const app = express();
app.use(session({
secret: "secret",
cookie: {
maxAge: 60000 * 60 * 24
},
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use('/auth', require('./routes/auth'))
const httpServer = http.createServer(app);
httpServer.listen(80, () => {
console.log("HTTP Server running on port 80");
});
auth.js
const express = require('express');
const passport = require('passport');
const router = express.Router();
router.get('/success', (req, res) => {
res.send("sucessful")
});
router.get('/forbidden', (req, res) => {
res.send("forbidden")
});
router.get('/', passport.authenticate('discord'));
router.get('/redirect', passport.authenticate('discord', {
failureRedirect: '/auth/forbidden'
}), function(req, res) {
res.redirect('/auth/success')
});
module.exports = router;
discordstrategy.js
const DiscordStrategy = require('passport-discord').Strategy;
const passport = require('passport');
var scopes = ['identify', 'guilds'];
passport.use(new DiscordStrategy({
clientID: '[redacted]',
clientSecret: '[redacted]',
callbackURL: '/auth/redirect',
scope: scopes
},
function(accessToken, refreshToken, profile, cb) {
console.log(profile.id)
}));

After Authing, discord and express use a cache system to store your user, so that you dont have to log in everytime. try going on incognito or a different account and logging in.

Related

Cannot authenticate user with Passport Local Strategy

I am using passport to implement a login function on my application. However, every time I try to authenticate the user, I cannot get passed the authentication and am redirected to the failure URL. I have confirmed that there is a user in the MongoDB database and the user supplied password is correct. However, I cannot get past the passport authentication. Can anyone please help me out ?
This is my index.js
const express = require('express');
const app = express();
const mongoose = require('mongoose');
const path = require('path');
const ejsMate = require('ejs-mate');
const loginRoutes = require("./routes/login");
const User = require('./models/users');
const session = require('express-session');
const userRoutes = require('./routes/user');
const passport = require('passport');
const localStrategy = require('passport-local');
sessionConfig = {
name: "session",
secret: 'BetterSecret',
resave: false,
saveUninitialized: true,
cookie: {
httpOnly: true,
expires: Date.now() + 604800000, //Date.NOW + No. of Miliseconds in the week
maxAge: 604800000
}
};
//Connection strings only beyond this line
mongoose.connect('mongodb://localhost:27017/myLoc').then(console.log("DB connected")).catch(error => handleError(error));
app.listen(5500, (req, res, next) => {
console.log("Connected");
});
//app.uses
app.use(express.urlencoded({ extended: true }));
app.use("/", loginRoutes);
app.use("/business", userRoutes);
app.engine('ejs', ejsMate);
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views')); //setting up the views directory
app.use(express.static(path.join(__dirname, 'public'))); //public directory to serve static content
app.use(session(sessionConfig));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new localStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
This is the router for the login:
const express = require('express');
const router = express.Router();
const users = require('../controllers/users');
const passport = require('passport');
router.route('/login')
.get(users.renderLoginForm)
.post(passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' }), users.login);
router.route('/register')
.get(users.renderRegisterForm)
.post(users.createNewUser);
module.exports = router;
and for the controller I just have a console.log for now
module.exports.login = (req, res, next) => {
console.log("I am here");
};

HTTP requests receive 404 in browser but work fine in Postman

I've deployed my app to Heroku and it builds fine and my React app is rendering pages correctly. However, when I try to submit a POST request to sign up a user or log a user in, I get a 404 error. I do not, however, have this problem when submitting requests from Postman. My front end is using React and Axios for submitting requests. Server is using Nodejs and Express. I was thinking it had something to do with CORS, but I've tried configuring CORS and it hasn't resolved the issue.
Front-end code for POST request:
axios.defaults.withCredentials = true;
signUp: function(userInfo) {
userInfo = {
email: userInfo.email,
password: userInfo.password,
firstName: userInfo.firstName,
lastName: userInfo.lastName,
mobileNumber: userInfo.mobileNumber
}
return axios.post('/users/signup', userInfo);
Server file
const express = require('express');
const session = require('express-session');
const passport = require('./config/passport');
const path = require("path");
const cors = require('cors');
const cookieParser = require("cookie-parser");
const app = express();
const SequelizeStore = require('connect-session-sequelize')(session.Store);
const db = require('./models');
const sessStore = new SequelizeStore({
db: db.sequelize
});
const http = require('http').Server(app);
const routes = require('./routes');
const PORT = process.env.PORT || 3000;
const corsConfig = {
origin: "https://example.herokuapp.com/",
credentials: true
}
if (process.env.NODE_ENV === 'production') {
app.use(express.static('client/build'));
app.use(cors(corsConfig));
}
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(session({
secret: process.env.SESSION_SECRET,
name: process.env.SESSION_NAME,
store: sessStore,
resave: false,
saveUninitialized: false }));
app.use(cookieParser());
app.use(passport.initialize());
app.use(passport.session());
app.use(routes);
app.get("*", function(req, res) {
res.sendFile(path.join(__dirname, "./client/build/index.html"));
});
db.sequelize.sync().then(() => {
http.listen(PORT, () => console.log(`Listening at http://localhost:${PORT}`));
});
Routes index file
const router = require("express").Router();
const usersRoutes = require('./users');
const isAuthenticated = require('../../config/middleware/isAuthenticated');
router.use("/users", usersRoutes);
Users Routes file
const router = require("express").Router();
const passport = require('../../config/passport');
const usersController = require("../../controllers/usersController");
router
.route('/signup')
.post(usersController.createNewUser);
router
.route('/login')
.post(passport.authenticate('local'), usersController.logUserIn);
Controller
createNewUser: function(req, res) {
db.User.create({
email: req.body.email,
password: req.body.password,
firstName: req.body.firstName,
lastName: req.body.lastName,
mobileNumber: req.body.mobileNumber
})
.then(() => res.sendStatus(200))
.catch((err) => res.send(err));
}
I resolved this. The url in the axios call was missing a piece. The reason this worked locally is because I had the proxy in React set to include the missing piece so axios calls done locally were always being sent to the right url, but they were not being sent to the right url in prod. Really relieved it was something so simple!

Axios then callback not working on successful Post request

Been working on figuring out user login/register with react and why my axios is not calling .then on successful post request to my api.
Server.js
//Node packages
const path = require('path');
//Required NPM Packages
const express = require('express'),
app = express(),
session = require('express-session'),
cors = require('cors'),
bodyParser = require('body-parser'),
mongoose = require('mongoose'),
MongoStore = require('connect-mongo')(session),
methodOverride = require('method-override'),
passport = require('passport'),
LocalStrategy = require('passport-local');
//MongoDB models.
const Product = require('./models/Product');
const User = require('./models/User');
//Routes.
const indexRoute = require('./routes/index');
const demoRoute = require('./routes/demos');
const blogRoutes = require('./routes/blogs');
const userRoutes = require('./routes/users');
//Port.
const PORT = 5000;
const DATABASE_URI = require('./config/database');
const mongoOptions = { useNewUrlParser:true, useUnifiedTopology:true};
//Connect to mongoDB.
mongoose.connect(DATABASE_URI, mongoOptions);
const sessionOptions = {
secret: 'somesecretword',
resave: true,
saveUninitialized: true,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}
//set session options
app.use(session(sessionOptions));
//Setup body-parser.
app.use(express.json());
app.use(bodyParser.urlencoded({extended:true}));
//Allow express/node to accept Cross-origin resource sharing.
app.use(cors());
app.use(express.static(path.join(__dirname, '..','client','build')));
//Setup method override.
app.use(methodOverride("_method"));
//Congifure passport.
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(function(req,res,next){
res.locals.currentUser = req.user;
next();
})
//register API routes to express.
app.use('/', indexRoute);
app.use('/demos', demoRoute);
app.use('/blogs', blogRoutes);
app.use('/users', userRoutes);
// //Register React routes to express
app.use('about', express.static(path.join(__dirname, '..','client','build')));
app.get('*', (req,res)=> {
res.sendFile(path.join(__dirname,'..','client','build','index.html'));
})
//listen to established port.
app.listen(PORT, () => {
console.log(`The server has started on port ${PORT}!`);
});
module.exports = app;
login route
router.post('/login', passport.authenticate('local'), (req, res) => {
console.log('success');
res.json({authenticated:true});
});
React front-end function
async function handleRegister(evt){
//Prevent default form redirect.
evt.preventDefault();
//Create a new user objec to pass into axios
const user = {
username: username,
password: password
}
//Send axios post request to nodeJS API.
await axios.post("http://*******/users/register", user)
.then((res) => {
console.log(res.data);
})
.catch((err) => {
console.log(err);
});
//Push react history back to index page.
}
Right now I'm using Passport.js with passport.local.mongoose Strategy and connect-mongo. When I go ahead and post to the login route with the correct users information, the callback on the back end returns success. As per the passport.authenticate method if auth is a success then we console.log and send res.json.
I've tried to use res.send, res.json, res.sendStatus but none of them seem to work. Am I missing some sort of setup with passport? As far as the documentation goes for passport-local-mongoose I shouldn't have to establish a config.
All I want to happen is that when I login I send a redirect to react and push the response route to react-router's history object via history.push(routeUrl);
I found out the problem. Was just an error on my part. Was working with the register function and not the login in function. The issue wasn't that I wasn't getting a response... Probably a queue for a break.

req.user undefined in other model

I have 2 modules
users
blogs
i have implemented users for login register with passport authentication . When i try to use current user data(req.user) in blog model it results 'undefined'.
i have share my code below
app.js
const express = require('express');
const app =express();
const path = require('path');
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended : false }));
app.use(bodyParser.json());
const Users = require("./routes/Users");
const Blogs = require("./routes/Blog");
app.use("/users",Users);
app.use("/blogs",Blogs);
app.set('views',path.join(__dirname, 'views'));
app.set('view engine','ejs');
app.listen(3000, function() {
console.log('Server started...');
});
users.js
const passport = require('passport');
const express=require('express');
const users = express.Router();
const models = require('../models');
const User = models.users;
var cookieParser = require('cookie-parser');
const session = require('express-session');
users.use(cookieParser());
users.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}));
users.use(passport.initialize());
users.use(passport.session());
require('../config/passport.js')(passport, User);
users.post('/register',passport.authenticate('local-register', {
successRedirect: '/users/profile',
failureRedirect: '/users/register'
}
));
users.post('/login',passport.authenticate('local-login', {
session: true,
successRedirect: '/users/profile',
failureRedirect: '/users/profile'
}
));
module.exports =users;
blogs.js
const express = require('express');
const blogs = express.Router();
const blogModel = require('../models/blogs');
blogs.get('/',(req,res) =>{
console.log(req.user) // RESULTS UNDEFINED
res.send('Blog List');
});
passport.js
const bCrypt = require('bcryptjs');
const LocalStrategy = require('passport-local').Strategy;
module.exports = function(passport, user) {
const User = user;
passport.use('local-register', new LocalStrategy( { usernameField: 'email', passwordField: 'password', passReqToCallback: true },
function(req, email, password, done) {
... ....
}
));
passport.use('local-login', new LocalStrategy({ usernameField: 'email', passwordField: 'password', passReqToCallback: true },
function(req, email, password, done) {
..... .....
}
));
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
const User =user;
User.findById(id).then((user) =>{
if (user) {
done(null, user);
} else {
done(user.errors, null);
}
});
});
}
You are initiating passport (which handles req.user) only for Users router, this way only routes starting with /users will actually have access to req.user.
In order to use req.user inside the Blogs module, you need to initiate passport for the entire express app (instead of just the users router).
You would probably want to move the initialization to the app.js file
app.use(bodyParser.urlencoded({extended : false }));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
I believe your problem is you are using multiple objects/instance of express packages and trying to pass from one to another. It won't work as expected. To make it working you should have multiple routes using the same express instance.

Passport local strategy not being called

Update: I have downloaded express-4.x-local-example and can't seem to get it working either. Is there something that I'm missing?
I'm trying to set a local strategy for passport but it's not being fired. After entering the credentials, the page redirects to failureRedirect.
app.js
const express = require('express')
, app = express()
, mainRouter = require('./controllers/mainRouter');
mainRouter(app);
mainRouter.js
const bodyParser = require('body-parser')
, passport = require('passport')
, passportConfig = require('../config/passport');
passportConfig(passport);
module.exports = (app) => {
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(passport.initialize());
app.use(passport.session());
app.post('/login', passport.authenticate(('local'), {
successRedirect: '/',
failureRedirect: 'login/',
})
);
}
passport.js
const LocalStrategy = require('passport-local').Strategy;
module.exports = (passport) => {
passport.use(new LocalStrategy({usernameField: 'email'},
(email, password, done) => {
console.log('This message is not being logged.');
})
);
}
Your not actually calling the strategy in your mainRouter.js file.
Before the app.post, add passport.use(passportConfig);

Resources