React Router intercepting API call to Express server - javascript

I'm using React Router with Passport.js to set up Facebook login. I've set up the express routes and passport config, but every time I hit the
<a href="/api/auth/facebook"> link on my client side, it makes a request to RR because of my express app with this line:
app.get('/*', function(req, res) {
res.sendFile(path.resolve(__dirname, '../client', 'build', 'index.html'))
});
As I am making a call to the server side route, it returns this error:
Warning: [react-router] Location "/api/auth/facebook" did not match any routes
How can I bypass React Router for this one particular route?
my user_routes.js file looks like:
'user strict';
var bodyparser = require('body-parser');
var User = require('../models/User.js');
module.exports = function loadUserRoutes(router, passport) {
router.use(bodyparser.json());
router.get('/auth/facebook', passport.authenticate('facebook', {
session: false,
successRedirect: '/chat',
failureRedirect: '/'
}));
router.get('/auth/facebook/callback', passport.authenticate('facebook', {
session: false,
successRedirect: '/chat',
failureRedirect: '/'
}));
router.post('/sign_up', passport.authenticate('local-signup', { session: false}), function(req, res) {
res.json(req.user);
});
router.post('/sign_in', passport.authenticate('local-login', { session: false}), function(req, res) {
res.json(req.user);
});
router.get('/signout', function(req, res) {
req.logout();
res.end();
});
//get auth credentials from server
router.get('/load_auth_into_state', function(req, res) {
res.json(req.user);
});
// get usernames for validating whether a username is available
router.get('/all_usernames', function(req, res) {
User.find({'local.username': { $exists: true } }, {'local.username': 1, _id:0}, function(err, data) {
if(err) {
console.log(err);
return res.status(500).json({msg: 'internal server error'});
}
res.json(data);
});
})
};

In express routes are matches in the order they get defined.
So before your /* route you need something to handle api requests.
app.get('/api/auth/facebook', passport.authenticate('facebook'))
app.get('/*', function(req, res) {
res.sendFile(path.resolve(__dirname, '../client', 'build', 'index.html'))
});

Related

How to configure route for oauth callback in Node.js

This works perfectly fine in the server.js:
app.get('/auth/google/callback',
passport.authenticate('google', {
failureRedirect: '/login'
}),
(req, res) => {}
);
But the following doesn't when used in route.js:
exports.googleCallback = function(req, res, next) {
passport.authenticate('google', { failureRedirect: '/login' });
const handler = function(req, res) {
// Successful authentication, redirect home.
res.redirect('/');
};
handler(req, res, next);
};
I have the following in route.js:
app.route(path + 'auth/google').get(auth.googleLogin);
What happens:
The second code directly goes to / path without waiting for Passport Google strategy to completely execute.
If I remove res.redirect('/'); It does not go anywhere and keep loading.
This worked just fine:
exports.googleCallback = function(req, res, next) {
passport.authenticate('google', { failureRedirect: '/login' })(req, res, next);
};
Added callback method on the passport.

Node.JS authorization

I want to create a simple application with auth system. When someone visits my page server must return authorization html page, than visitor can fill the inputs and send login and password through socket.io to server. And if the values are correct, server sends second html page to client. I know that I can use this code and redirect on client side:
app.get('/page1', function(req, res){
res.sendFile(__dirname + '/page1.html');
});
app.get('/page2', function(req, res){
res.sendFile(__dirname + '/page2.html');
});
But I want users to always stay on the same address, it must always be example.com/
You can use express middleware for authentication.
function authCheck(req,res,next){
//Your auth check will be here
if(isValidUser){
next();
}
else{
res.sendFile(__dirname + '/login.html');
}
}
app.get('/afterlogin', authCheck, function(req, res){
res.sendFile(__dirname + '/afterlogin.html');
});
You can use Passport for authentication provider.
Then you can register some authentication middleware like so:
// auth.js
module.exports = {
isGuest: (req, res, next) => {
if (req.isAuthenticated()) {
res.redirect('/');
} else {
next();
}
},
isAuthenticated: (req, res, next) => {
if (req.isAuthenticated()) {
next()
} else {
res.redirect('/users/login')
}
},
};
Then you can apply the middleware on your routes like so:
// users.js
let express = require('express'),
router = express.Router(),
usersController = require('../controllers/usersController'),
auth = require('../middlewares/auth');
router.get('/register', auth.isGuest, (req, res) => {
usersController.showRegisterPage(req, res);
});
router.post('/register', auth.isGuest, (req, res) => {
usersController.register(req, res);
});
router.get('/login', auth.isGuest, (req, res) => {
usersController.showLoginPage(req, res);
});
router.post('/login', auth.isGuest, (req, res) => {
usersController.login(req, res);
});
router.post('/logout', (req, res) => {
usersController.logout(req, res);
});
router.get('/profile/:username', auth.isAuthenticated, (req, res) => {
usersController.showProfilePage(req, res);
});
Hope this helps.

Node.js, express, passport authentication "Bad Request"

I'm using Cloud 9 to setup a basic social media website and I am having trouble with registration and authentication of users. I'm using Node.js, express and passport for authentication, and mongoDB as a database.
// PASSPORT Setup //
app.use(require("express-session")({
secret: "I am the best",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
// INDEX Page
app.get("/", function(req, res) {
res.render("landing-page");
});
// REGISTER NEW
app.get("/register", function(req, res) {
res.render("user/register");
});
// REGISTER CREATE
app.post("/register", function(req, res) {
var user = req.body.user;
var newUser = new User({
username: user.email,
firstName: user.firstName,
lastName: user.lastName,
});
User.register(newUser, user.password, function(err, user) {
if(err) {
console.log(err);
return res.render("user/register");
}
passport.authenticate("local")(req, res, function() {
res.redirect("/");
});
});
});
// Login routes
app.get("/login", function(req, res) {
res.render("login");
});
app.post("/login", passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/login"
}) , function(req, res) {
});
// Logout route
app.get("/logout", function(req, res) {
req.logout();
res.redirect("/");
});
However whenever I run this, when I sign up a new user, it gives me a webpage with just "Bad Request", however the user is created in the database.
Look at this answer; the bad request is not a problem with your passport method: that indicates the request you try to make is not correct:
Did you set the head at: Content-Type: application-json?
Also update the bodyParser to the last version. This solved a similar problem I had.

Page callback not load with NodeJS Express Passport-facebook

I have an application node js using express for authentication via facebook but the url /auth/facebook/callback does not load.
Dependencies version:
Express: 4.13.3
Passport 0.3.0
Passport-facebook 2.0.0
app.js
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
passport.use(new FacebookStrategy({
clientID: '806175282757975',
clientSecret: '*************',
callbackURL: "http://localhost:3000/auth/facebook/callback"
},
function(accessToken, refreshToken, profile, done) {
process.nextTick(function () {
return done(null, profile);
});
}
));
app.use(function(req,res,next){
req.passport = passport;
next();
});
app.use('/', routes);
app.use('/users', users);
module.exports = app;
routes/index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.get('/auth/facebook', function(req, res, next){
req.passport.authenticate('facebook')(req, res, next);
});
router.get('/auth/facebook/callback', function(req, res, next){
req.passport.authenticate('facebook', { successRedirect: '/',
failureRedirect: '/login' });
});
module.exports = router;
No error is returned on console.
In routes/index.js in /auth/facebook/callback route you forgot about calling authenticate method with req, res, next arguments. That is why your application was stuck ('next' callback was never called).
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.get('/auth/facebook', function(req, res, next){
req.passport.authenticate('facebook')(req, res, next);
});
router.get('/auth/facebook/callback', function(req, res, next){
req.passport.authenticate('facebook', {
successRedirect: '/',
failureRedirect: '/login' }
)(req, res, next); // missing function call
});
module.exports = router;

Cannot GET /auth/twitter/callback while using twitter oauth in nodejs

I'm trying to do twitter oauth in nodejs using passportjs but getting error
Cannot GET /auth/twitter/callback?oauth_token=alksdkalsjdsjd23232378skjdfjsdhf&oauth_verifier=234jjh23j4k234k23h4j2h342k34hj
Here is my node js code
var express = require('express')
, passport = require('passport')
, util = require('util')
, GoogleStrategy = require('passport-google').Strategy
, TwitterStrategy = require('passport-twitter').Strategy;
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
passport.use(new TwitterStrategy({
consumerKey: 'xxxxxxxxxxxxxxxxxxxx',
consumerSecret: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
callbackURL: 'http://127.0.0.1:3000/auth/twitter/callback'
},
function(token, tokenSecret, profile, done) {
process.nextTick(function () {
return done(null, profile);
});
}
));
var app = express();
// configure Express
app.configure(function() {
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.logger());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({ secret: 'keyboard cat' }));
// Initialize Passport! Also use passport.session() middleware, to support
// persistent login sessions (recommended).
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(__dirname + '/../../public'));
});
app.get('/', function(req, res){
res.render('index', { user: req.user });
});
app.get('/login', function(req, res){
res.sendfile('./views/auth.html');
});
app.get('/auth/twitter', passport.authenticate('twitter'));
app.get('auth/twitter/callback',
passport.authenticate('twitter', { successRedirect: '/success',
failureRedirect: '/login' }));
app.get('/success', function(req, res){
res.send("success logged in");
});
app.listen(process.env.PORT || 3000);
EDIT
There is missing / in auth/twitter/callback route definition.
Also for the routers /auth/twitter and auth/twitter/callback, passport.authenticate() as middleware will do the authentication, and you should have route handling functions.
So the definition of your routes should look something like:
app.get('/auth/twitter',
passport.authenticate('twitter'),
function(req, res) {}); // empty route handler function, it won't be triggered
app.get('/auth/twitter/callback',
passport.authenticate('twitter', {
successRedirect: '/success',
failureRedirect: '/login' }),
function(req, res) {}); // route handler
You don't need the empty route handler function(req, res) {} - you can just leave the argument out and express will understand you don't plan on ever using the handler

Categories