Mocking different passport.js strategies in an integration test - node.js

In the /config/passport.js file I've defined and am using different strategies:
var
sails = require('sails'),
passport = require('passport'),
LocalStrategy = require('passport-local').Strategy,
CustomStrategy = require('passport-custom').Strategy,
GoogleStrategy = require('passport-google-oauth').OAuth2Strategy,
FacebookStrategy = require('passport-facebook').Strategy;
passport.use(new LocalStrategy({...}, function(email, password, done){...}));
passport.use('my-custom-strategy', new CustomStrategy(function (req, done){...}));
... same for FB and Google
And I want to do an integration test, where I mock the result returned to the controller from these strategies (and focus on the rest of the controller and service processing). Specifically, mocking the custom-strategy is important for me.
I could find some scarce examples like this post and the followup link, but could not relate that much to my use cases.
Can anyone give me some code examples that I can start building my tests from?
var expect = require('chai').expect
, request = require('supertest')
, sinon = require('sinon')
, passport = require('passport');
describe('/auth', function () {
it('should return correct authentication response with tokens', function (done) {
// here I want to mock the custom strategy (or any other)
var requestBody = {
// some info
};
request(url)
.post('/auth')
.send(requestBody)
.end(function (err, res) {
if (err) {
return done(err);
}
console.log(res.body);
done();
});
});
});

To me from your question it is not clear exactly what functions you want to mock.
I would interpret two problem scenarios here:
Either you want to mock the authentication itself, f.e. to test API controllers relying on an authenticated user. For this scenario the provided links are one possible way. Just write another authentication mechanism which fakes a logged in user. The mock strategy would not go through all the code than a real strategy would but just does the minimum what needs to be done. Maybe also manipulation the database if needed. There is nothing much to be added here if your question is not more specific.
The other scenario is that you want to test the strategy itself. So you want to mock external i/o which your strategy relies on. This can be user input / http traffic and/or database interaction. Since user input usually is collected on the server using http traffic and lots of strategies use external servers to authenticate I would suggest to mock the actual http traffic the way you need it to test your strategy. You can do this using nock. For the database interactions you could f.e. setup a testing db.

Related

Microservices API Authentication with API Gateway in NodeJS/Express

I'm creating a Microservice architecture using Node JS and Express. I know that one of the main features of Microservices are a service oriented architecture where teams can design, develop and ship their applications independently. So in my design I think that each microservice offers their APIs and they communicate between each other with the API in this way each Microservice is independent and have it's own life waiting for request.
I am writing this question because I have several doubts about
authentication and communication between microservices.
For the autentication I have made some test with JWT to authenticate the API of a Microservice and all works fine, this is an example of express middleware for authentication:
const tokenCheck = (req, res, next) => {
let token = getToken(req);
if (token) {
jwt.verify(token, "password, (err, decoded) => {
if (err) {
throw "Failed to authenticate token.";
} else {
req.user = decoded;
next();
}
});
} else {
throw "No token provided.";
}
};
Used in this way:
router.get("/", tokenCheck, Controller.get);
So each route is protected with a layer of autentication.
Instead about communication between microservices I read the best way is to use an API Gateway and I found this library to do it, furthermore i read that it's better to add the authentication middleware inside the API Gateway because if you re-implement these things in each single microservice, you are duplicating the code at first, but more importantly you have two different pieces of software to maintain.
Now my question are two:
1) Is right use an API gateway like this to make communication between microservices?
2) If I move the authentication middleware from the microservices to the API Gateway I have to remove the middleware from the API routes and in this way the API will be unprotected if someone other than the gateway make requests and I think this is wrong because anyone can call that routes, instead if I mantain the middleware also is the mircorservice the code is duplicated, can anyone tell me what is the right way to do it?
I have been working on Node.js from past couple of years and here is my understanding, hope this helps you clear your thoughts.
The answer to your question:
Let me explain to you the work of both the parts you have stated in the question.
http-proxy-middleware
Proxy: In simple words, the proxy means duplicate clone to turn your traffic too.
Read more: What is the proxy server?
Your custome middleware
Your custom middleware is the project specific code to check if all the requests are authenticated.
It would check if the request has a token and if the token is valid.
Conclusion:
You need your custom middleware compulsorily. Another one (http-proxy-middleware
) is optional.
Update:
Now my question are two:
Is right use an API gateway like this to make communication between
microservices?
Answer: No, it is not the right way.
If I move the authentication middleware from the microservices to
the API Gateway I have to remove the middleware from the API routes
and in this way the API will be unprotected if someone other than the
gateway make requests and I think this is wrong because anyone can
call that routes, instead if I mantain the middleware also is the
mircorservice the code is duplicated, can anyone tell me what is the
right way to do it?
For this, you can impose the authentication middleware on app so that all the routes execute the middleware.
Update your server code.
// Init App
const App = Express();
// Authentication code
App.use((req, res, next) => {
let token = getToken(req);
if (token) {
jwt.verify(token, password, (err, decoded) => {
if (err) {
throw "Failed to authenticate token.";
} else {
req.user = decoded;
next();
}
});
} else {
throw "No token provided.";
}
});

Apollo GraphQL Server authentication with passportJS

I am trying to authenticate a user before allowing access to my '/graphql' endpoint.
According to apollo-server documentation regarding setting a context I can do something like this.
app.use(
'/graphql',
bodyParser.json(),
graphqlExpress(req => {
// Some sort of auth function
const userForThisRequest = getUserFromRequest(req);
return {
schema: myGraphQLSchema,
context: {
user: userForThisRequest,
},
// other options here
};
}),
);
I am trying to use passportJS's authenticate() function in the placeholder for "Some sort of auth function", but I can't seem to understand how to utilize the 'req' parameter that I have access to. Should I call passport.authenticate() after the bodyParser middleware or inside the graphqlExpress method?
So my question is how can I use passportJS's authenticate mechanism in this context? Also, is this the best way to implement Authentication on Apollo-server?
There's a couple of different ways you could do this -- depending on the type of response you want to send back to your client when authentication fails and the how much you need to fine-tune the authentication process.
Passport's authenticate function is effectively just express middleware, so you can do something like:
app.use(
'/graphql',
bodyParser.json(),
authenticate(),
graphqlExpress(req => ({
schema: myGraphQLSchema,
context: {
user: getUserFromRequest(req),
},
}));
);
authenticate will send a response with a 401 status if authentication fails (the response itself depends on how you configured the verify callback in your passport strategy). That means if authentication fails, the Apollo server middleware will never be called.
Alternatively, you could avoid using authenticate and handle checking the authentication yourself. This can be done at the resolver level, or for all resolvers by utilizing graphql-tool's addSchemaLevelResolveFunction.
import { addSchemaLevelResolveFunction } from 'graphql-tools'
addSchemaLevelResolveFunction(executableSchema, (root, args, ctx, info) => {
if (!ctx.user) throw new CustomAuthenticationError()
})
The biggest difference is that your response will now return a 200 status, and will include a null data property and an errors array that includes the authentication error.
Of course, the second approach also lets you fine tune your authentication logic -- if you want to only limit a subset of queries or mutations to be only available to authenticated users, for example. Barring that, I don't know if either approach is necessarily better.

What's the better way of implementing security with MEAN.js

I'm working with mean.js, and I have a little doubt about authentication and authorization here...
MEAN.js come with a out of the box passport.js implementation that seems to be working good enough for me just to know when a user is logged in. But at the moment of authorization some question pop up in my mind.. doing my research I reach some answers and I don’t know what is the best way of implementing security API calls in my app.
So far, I'm taking this solution:
Using express.all() function to set in one file all my authorization functions ( I guess it is a good practice right ? ).. creating a file with the following code example:
'use strict';
var passport = require('passport');
module.exports = function(app) {
app.route('/private/p/*').all(function(req, res, next){
if(!req.isAuthenticated()){
res.send(401);
}else{
next();
}
});
app.route('/private/byRoles/*').all(function(req, res, next){
if(!req.isAuthenticated()){
res.send(401);
}else{
var urlRoles = ['admin', 'godlike'];
// ROLE LOGICS THAT ARE GOING TO BE ADDED TO MY USER
// GETTING MY USER ID BY THE DE-SERIALIZE PASSPORT FUNCTION AND GETTING MY
// MONGO MODEL FOR MY USER, WITH THE INFO OF ROLES IN THERE AND DOING
// SOME LOGICS HERE ABOUT THE ROLES AND URL PATTERN.
if ( hasRole(urlRoles, user.roles)){
next();
}else{
res.send(401);
}
}
});
};
So far this is the solution that I'm planning to implement, but I would like to be sure of what I'm doing here... is there a better way of implementing authorization in mean.js ? Is this authorization middle-ware wrong implemented with passport? I don't sure if is necessary to implement another strategy to this.. or if this implementation has a security lack ( sure it has to ).. is better to use Oauth or using api token ??? what should be the architecture to secure an app made in MEAN.js supporting roles and permissions ?? also in the future I would need to secure my socket.. I was looking at passport-socketio.. but not sure if is there a better solution.
I use JWT's for my angular apps. There are many articles out there about the benefits for using tokens instead of sessions or cookies Cookies vs Tokens. Getting auth right with Angular.JS.
You can do everything you want with JWT, roles for backend and frontend, securing sockets is also possible and there are packages for this functionality. You do not need passport if you using tokens. You check the the credentials one time and store the token in the browsers local storage. There are many packages for express and JWT Express-JWT
For a closer look at JWT jwt.io

user authentication using socket.io

I've red this tutorial: http://howtonode.org/socket-io-auth.
It shows how to authenticate users using express and socket.io.
But is there a way to authenticate users using only socket.io without the need for express?
edit:
For session handling I use RedisStore (https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO).
Whats left is a module to create authentication cookies.
Does anyone know of a socket.io implementation I can use to create an authentication cookie like you can do with session handling?
I know this is bit old, but for future readers in addition to the approach of parsing cookie and retrieving the session from the storage (eg. passport.socketio ) you might also consider a token based approach.
In this example I use JSON Web Tokens which are pretty standard. You have to give to the client page the token, in this example imagine an authentication endpoint that returns JWT:
var jwt = require('jsonwebtoken');
// other requires
app.post('/login', function (req, res) {
// TODO: validate the actual user user
var profile = {
first_name: 'John',
last_name: 'Doe',
email: 'john#doe.com',
id: 123
};
// we are sending the profile in the token
var token = jwt.sign(profile, jwtSecret, { expiresInMinutes: 60*5 });
res.json({token: token});
});
Now, your socket.io server can be configured as follows:
var socketioJwt = require('socketio-jwt');
var sio = socketIo.listen(server);
sio.set('authorization', socketioJwt.authorize({
secret: jwtSecret,
handshake: true
}));
sio.sockets
.on('connection', function (socket) {
console.log(socket.handshake.decoded_token.email, 'has joined');
//socket.on('event');
});
The socket.io-jwt middleware expects the token in a query string, so from the client you only have to attach it when connecting:
var socket = io.connect('', {
query: 'token=' + token
});
I wrote a more detailed explanation about this method and cookies here.
Instead or wiring up authentication and session handling code manually, I'd recommend to go with a dedicated module, such as session.socket.io (but please note that this is a module that requires Express as well).
I guess (but don't know) that there were downvotes because you need some sort of session handling, and you most probably do not want to do this manually as well ;-). Hence it's a quite good idea to stick with Express here.
Nevertheless, it's an interesting question, although I can not answer on how to do it without Express.
I am quite new to node.js, just started a few days ago. and i only can answer to the first part to the question, which is user authentication without the use of express. and i also got no session-style handling yet.
the reason I am still answering to this question is to help out other people who are new to node with a more simple alternative solution for the beginning.
the solution i am currently using in my learning project (a socket.io - based chat, what else?) is using the http server for authentication.
if you can't get a valid authentication on the http server, you'll never get access to the page with the socket.io interface.
the user authentication on the http server is handled by reading out some POST data. only if the POST data is valid user data the user is allowed to move on to the chat where the socket.io interface is.

Make a NodeJs application private on Heroku

I'm trying to make a NodeJS application on Heroku private so that only developers can see it. Is there a simply way to do that, like basic auth? (All of the solutions I keep finding are specific to Ruby apps).
If you want to leverage basic authentication, here are two options: http-auth and Passport. http-auth is a very simple module and Passport is a powerful module with alternatives for authentication. Both modules provide code examples ranging from basic code to Express framework integration.
I have the same problem. I managed to get one solution working that may work for you but wasn't suitable for me as it seems to interfere with the built in user login from angular-fullstack.
I just wanted a quick way to password protect the app so that only developers and stakeholders could see it. https://www.npmjs.org/package/http-auth seems to do the trick.
This involves add http-auth to your project (npm install http-auth --save). Then you'll need to find the file where your createServer is defined and the code there.
If you're using Express you can do something like this
// HTTP Authentication
var preAuth = require('http-auth');
var basic = preAuth.basic({
realm: "Restricted Access! Please login to proceed"
}, function (username, password, callback) {
callback( (username === "user" && password === "password"));
}
);
// Setup server
var app = express();
app.use(preAuth.connect(basic));
var server = require('http').createServer(app);
If not then you can try one of the options from the http-auth documentation e.g.
// Authentication module.
var auth = require('http-auth');
var basic = auth.basic({
realm: "Simon Area."
}, function (username, password, callback) { // Custom authentication method.
callback(username === "Tina" && password === "Bullock");
}
);
// Creating new HTTP server.
http.createServer(basic, function(req, res) {
res.end("Welcome to private area - " + req.user + "!");
}).listen(1337);
Here are also a couple of related threads with somewhat similar approaches.
express.basicAuth throwing error
Basic HTTP authentication in Node.JS?

Resources