Double authenticator with JWT in NodeJS Express - node.js

I'm currently trying to build an express server that allows the user to authenticate via two third-party services: Google and Steam. The authentication is done via JWT and it works when only one of the two services is activated, but I can't get the protected routes to work when the user is logged in using one of the two services.
The code:
const express = require('express');
const bodyParser = require('body-parser');
const {gAuth, gProtect} = require('./auth/google_auth');
const {sAuth, sProtect} = require('./auth/steam_auth');
const app = express();
gAuth(app);
sAuth(app);
//middlewares
app.use(express.static('views'));// folder in which to put the static files (html, css, js client)
app.use(bodyParser.json({limit: '50mb'})); // read json
//middlewares (just for the widget)
app.use(bodyParser.urlencoded({ extended: true , limit: '50mb'})); // read form enctype data
app.set('view engine', 'ejs'); // set the engine render ejs for dynamic building of html pages with ejs tags
//set up routers for v1 app
const genericRouter = require('./routes/generic_router'); //testing if the application is working
const secureRouter = require('./routes/secure_router'); //testing if normal auth is working
//set up routers for latest version app
app.use('/', genericRouter);
app.use('/', gProtect(), secureRouter);//protected end-points (requiring auth)
app.use('/', sProtect(), secureRouter);
module.exports = app;
The problem is in the
app.use('/', gProtect(), secureRouter);//protected end-points (requiring auth)
app.use('/', sProtect(), secureRouter);
bit, since the second app.use overwrites the first, making all authentication attempts with Google fail. What can I do to make it so that the user can access the protected routes either with Google or Steam?

Use different endpoints
app.use('/', genericRouter);
app.use('/google', gProtect(), secureRouter);
app.use('/steam', sProtect(), secureRouter);

Related

I have problems to run server.js in terminal

enter image description here[
// Setup empty JS object to act as endpoint for all routes
projectData = {};
// Require Express to run server and routes
const express = require('express');
const app = express();
// Start up an instance of app
const PORT = 8080;
app.listen(PORT, () => {
console.log('Hi');
console.log(`the port that we will use is ${port}`);
});
/* Middleware*/
//Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Cors for cross origin allowance
app.use(cors());
// Initialize the main project folder
app.use(express.static('website'));
// Setup Server
app.post('/link', function(req,res) {
});
What should i do to run this in terminal
*I tried alot of solutions bot it's not working
in the terminal[
1.
it can not find the file
]3*
I think you need to install the 'body-parser' library and send it to call in your file
npm install body-parser
const bodyParser = require('body-parser');
app.use(bodyParser.json());
You don't need to use bodyparser if you use latest or after 4.0 version of Express.js. You can use
app.use(express.json()) // Parse Json Bodies
app.use(express.urlencoded()); //Parse URL-encoded bodies
as middlewares instead, without any package. They will solve your problem.

Express + React + Heroku can't find a file

i want to get my app working on Heroku, But there is on problem. Heroku server can't find the images. On developmnt everything is working correctly. Images are loaded propertly. On heroku everything works correctly. Asking for json /api/articles gives in result json. Router also working. But images gives not found. In tag and fetch() .
code => https://github.com/bartek-fecko/cinema-app
The image file exists on heroku(i looked to the bash on heroku.com)
var express = require('express');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, '../client/build')));
app.use('/api', indexRouter);
app.use('/api/users', usersRouter);
app.use(express.static(path.join(__dirname, '/assets/images')));//i'm sending a file
app.get('/images/:fileName', (req, res) => {
res.sendFile(path.join(__dirname, `/assets/images/${req.params.fileName}`)); //here also i'm sending a file
});
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname, '../client/build/index.html'));
});
module.exports = app;
<P.Wrapper>
<img src="spider-man-far-from-home.jpg" alt="no img"/>
<img src="/images/spider-man-far-from-home.jpg" alt="no img"/>
</P.Wrapper>
I'm getting a 404 error. And I tried everything and it doesn't work. The same for fetching fetch('/images/ ...') and so on.
From your code, you are having 2 servers:
Backend server (inside src)
Frontend server (inside client)
Since when you are starting them, they are of different servers, meaning that they either would be running on different IPs or the same IP but different Ports.
This means that your fetch of the image in the client's App.tsx would most likely be referencing the wrong host.
fetch('/images/spider-man-far-from-home.jpg')
Try using a full URL with both Host and Port in the fetch method and see if it works for you.
Yeah. woow. It's working now. The problem was exactly like Yee Hui Poh said. So in production i have to fetch to locallhost:8080/images/spider-man-far-from-home.jpg
where 8080 is backend server.

Router is mishandling static file load

In developing my website I ran across an issue with the way that my static CSS, JS, and image files are being loaded to my site. Once I navigate past the .index file or any route tree, my static directory misloads and the route index suddenly is added to the static file directory path.
I have written a yelpcamp app that I am modeling this app off of that works fine as I have it written, but this for some reason is throwing this specific error I can not find any resources to help correct.
Main app.js file that has all declarations and static file load
// REQUIREMENTS
var express = require("express"),
app = express(),
bodyParser = require("body-parser"),
mongoose = require("mongoose"),
methodOverride = require("method-override"),
nodemailer = require("nodemailer"),
expressSanitizer= require("express-sanitizer"),
// MODELS
blog = require("./models/blog"),
// ROUTES LOCATIONS
indexRoutes = require("./routes/index"),
blogRoutes = require("./routes/blog"),
contactRoutes = require("./routes/contact");
// SETUP
mongoose.connect("mongodb://localhost/*ChangedForPrivacy*");
app.use(bodyParser.urlencoded({extended: true}));
app.set("view engine", "ejs");
app.use(express.static(__dirname + "/public"));
app.use(methodOverride("_method"));
// ROUTE INDEX
app.use("/", indexRoutes);
app.use("/contact", contactRoutes);
app.use("/blog", blogRoutes);
This is the blog.js file in my routes folder where I noticed the static files loading correctly
// REQUIREMENTS
var express = require("express"),
Posts = require("../models/blog"),
router = express.Router();
// INDEX- SHOW ALL Posts
router.get("/", function(req,res){
// find all POSTS
Posts.find({}, function(err, allPosts){
if(err){
console.log(err);
} else{
// this is index because lots of paths are derived from it (landing pages are separate entities)
res.render("blog/home",{posts: allPosts});
}
});
});
// NEW (FORM PAGE)
router.get('/new', function (req,res){
res.render("blog/newpost");
})
// CREATE (POST TO PAGE)
// EDIT (PUT TO PAGE)
// DELETE
// EXPORT TO ROUTER
module.exports = router;
the /blog/home page loads the static CSS, JS perfectly but once you get to /blog/newpost it changes the path of the static files to now include the /blog in it. I would expect if the first app.get in the route structure would work they would all follow, but I am at a loss why it keeps adding the additional route directory.
I found my mistake in my partials/header.ejs file. I left out the "/"before the root of my static CSS/JS files so the router followed its path and added the route as it correctly should have.

passing objects (passport) between routes

Think what I am trying to do should be relatively easy, but I am loosing the thread, and potentially the will to do this.
Setting up a node application using node and express 4. And I use passport for authentication. Followed an absolutely amazing guide by scott.io which did the trick nicely https://scotch.io/tutorials/easy-node-authentication-setup-and-local
And it works a charm. However, I want to separate my routes, because I like keeping things tidy (thats a lie, but I intend to keep the lie living).
My plan was to have four sets of routes.
api (mapped to /api, using the file ./routes/api.js)
index (mapped to /, using the file ./routes/index.js)
auth (mapped to /auth, keeps track of all authentication, callbacks as well as some activator and other bits)
Now to my issue, I need to make the passport available to app (or get api.js and indes.js to be able to call functions in passport.js) and I can't quite figure out how.
My plan was to initiate passport like so:
var passport = require('passport');
app.use(session({secret: 'Not-telling-you)',
saveUninitialized: true,
resave: true
})); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
//Configuring the passports
require('./config/passport')(passport);
That should give me passport available in app
Next to load the route modules
var auth = require('./routes/auth')(app, passport);
var users = require('./routes/users')(app,passport);
var activator = require('./routes/activator')(app,passport);
This SHOULD allow me to access them in the modules?
Map all toutes in app
app.use('/api', api);
app.use('/auth', auth);
app.use('/', index);
And then write the modules as follows (this is a super simple version of auth)
var bodyParser = require('body-parser');
var activator = require('activator');
var express = require('express');
var router = express.Router();
//Lets read the configuration files we need
var activatorCfg = require('../config/activator.js')
var cfgWebPage = require('../config/webpage.js');
//So we can read the headers easily
router.use(bodyParser.json()); // support json encoded bodies
router.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
//Activating activator, so we can actively activate the actives
activator.init({user: activatorCfg, transport: activatorCfg.smtpUrl , from: activatorCfg.fromEmail, templates: activatorCfg.templatesDir});
router.get('/login', function(req, res) {
res.render('login.ejs', { title: 'Betchanow - Social betting as it should be' , loginUrl: cfgWebPage.loginUrl, trackingID: cfgWebPage.googleTracking.trackingID, message: req.flash('loginMessage') });
});
module.exports=function(app, passport) {
router
}
My problem is that if I do that, express complains that
throw new TypeError('Router.use() requires middleware function but got a
^
TypeError: Router.use() requires middleware function but got a undefined
If I just return the router (skip wrapping it in a function) I end up with a
var search = 1 + req.url.indexOf('?');
^
TypeError: Cannot read property 'indexOf' of undefined
So is there a right, simple or preferably right and simple way of achieving this?
Think the trick would be to pass app and passport (or only passport), think is I need access to either data or functions from passport in all three, and as I was planning to play with ACL as well, wanted to add that to auth to make my life simple as well.
============== EDIT =============
So here is my issue.
If I now do a post to the authentication route (code below)
//Lets load the modules, note the missing passport
var bodyParser = require('body-parser');
var activator = require('activator');
var express = require('express');
var router = express.Router();
//Lets read the configuration files we need
var activatorCfg = require('../config/activator.js')
var cfgWebPage = require('../config/webpage.js');
//So we can read the headers easily
router.use(bodyParser.json()); // support json encoded bodies
router.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
//Activating activator, so we can actively activate the actives
activator.init({user: activatorCfg, transport: activatorCfg.smtpUrl , from: activatorCfg.fromEmail, templates: activatorCfg.templatesDir});
//Lets start with our routes
// process the login form
router.post('/login', passport.authenticate('local-login', {
successRedirect : '/', // redirect to the secure profile section
failureRedirect : '/login', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
module.exports=function(app, passport) {
return router;
}
I end up with the issue that the route code (./routes/auth.js) have no clue what passport is. (loded in the app as follows):
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
//Configuring the passports
require('./config/passport')(passport);
You'll be getting the error because you're not returning the router.
module.exports=function(app, passport) {
return router;
}
EDIT:
You won't be able to access the passport property because you're not passing it around or setting it anywhere. As I'm not sure how passport works (whether it acts as a singleton or not), so you have a couple of options in your routes file:
var passport = require('passport')
which may "just work", or
var passport; // at the top of your routes file
// your routes
module.exports = function(app, _passport) {
passport = _passport;
return router;
}
A third option is to wrap your entire routes in the exports method:
// your requires here
module.exports = function(app, passport) {
//So we can read the headers easily
router.use(bodyParser.json()); // support json encoded bodies
router.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
//Activating activator, so we can actively activate the actives
activator.init({user: activatorCfg, transport: activatorCfg.smtpUrl , from: activatorCfg.fromEmail, templates: activatorCfg.templatesDir});
//Lets start with our routes
// process the login form
router.post('/login', passport.authenticate('local-login', {
successRedirect : '/', // redirect to the secure profile section
failureRedirect : '/login', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
return router;
}

Scripts and css files not loading with jade + node js

I am learning mean stack development. I am using working out with some examples. I am trying to load my css files and javascript files in the jade file. files are appearing in the console --> Sources. But all the css files are loading with empty data and all the js files are loading with html data.
I am having my server.js like this
var express = require("express");
var stylus = require("stylus");
var logger = require("morgan");
var bodyParser = require("body-parser");
var env = process.env.NODE_ENV = process.env.NODE_ENV || 'development';
var app = express();
function compile(str,path) {
return stylus(str).set('filename', path);
}
app.set('views', __dirname + '/server/views');
app.set('view_engine', 'jade');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(stylus.middleware({
src: __dirname + '/public',
compile:compile
}));
//defining routes
app.get('*', function (req,res) {
res.render('index.jade');
});
var port = 3030;
app.listen(port);
console.log('starting listening....');
How to load the files properly in this scenario?
The requests for client side resources are not being handled by anything in your app, which means they get handled by your "catch-all" handler (app.get('*', ...)), which returns HTML (which explains why you are seeing HTML being returned for jQuery, for instance).
You want to use a static file handler in your app to handle those requests:
app.use(express.static(__dirname));
The __dirname argument points to the directory that holds your client side resources files, so you may need to change this.
Also, make sure that you add this line above your catch-all handler, otherwise the requests will still be handled by that instead of the static file handler.

Resources