Skip to content

Instantly share code, notes, and snippets.

@mweibel
Last active December 5, 2022 03:33
Show Gist options
  • Star 42 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mweibel/5219403 to your computer and use it in GitHub Desktop.
Save mweibel/5219403 to your computer and use it in GitHub Desktop.
Mock passport.js with an own strategy
/**
* Author: Michael Weibel <michael.weibel@gmail.com>
* License: MIT
*/
var passport = require('passport')
, StrategyMock = require('./strategy-mock');
module.exports = function(app, options) {
// create your verify function on your own -- should do similar things as
// the "real" one.
passport.use(new StrategyMock(options, verifyFunction));
app.get('/mock/login', passport.authenticate('mock'));
};
/**
* Author: Michael Weibel <michael.weibel@gmail.com>
* License: MIT
*/
"use strict";
var passport = require('passport')
, util = require('util');
function StrategyMock(options, verify) {
this.name = 'mock';
this.passAuthentication = options.passAuthentication || true;
this.userId = options.userId || 1;
this.verify = verify;
}
util.inherits(StrategyMock, passport.Strategy);
StrategyMock.prototype.authenticate = function authenticate(req) {
if (this.passAuthentication) {
var user = {
id: this.userId
}
, self = this;
this.verify(user, function(err, resident) {
if(err) {
self.fail(err);
} else {
self.success(resident);
}
});
} else {
this.fail('Unauthorized');
}
}
module.exports = StrategyMock;
/**
* Author: Michael Weibel <michael.weibel@gmail.com>
* License: MIT
*/
var request = require('supertest')
, superagent = require('superagent')
, path = require('path')
, app = require(path.join(process.cwd(), 'index.js'))()
, passportMock = require(path.join(process.cwd(), 'src', 'shared', 'test', 'passport-mock'));
describe('GET /protected-resource authorized', function() {
var agent = superagent.agent();
beforeEach(function(done) {
passportMock(app, {
passAuthentication: true,
userId: 1
});
request(app)
.get('/mock/login')
.end(function(err, result) {
if (!err) {
agent.saveCookies(result.res);
done();
} else {
done(err);
}
});
})
it('should allow access to /protected-resource', function(done) {
var req = request(app).get('/protected-resource');
agent.attachCookies(req);
req.expect(200, done);
});
});
@ilanbiala
Copy link

Can you give an example of a verifyFunction implementation?
How would this work if my app is instantiated once at the beginning of all the tests and the app instance isn't available during the test? The issue I see is that I can't pass in app to passportMock() and so I can't register the middleware and route.

@dmitry-tuzenkov
Copy link

You can see an example here:
https://github.com/jaredhanson/passport-local#configure-strategy
And I think verifyFunction for auth success case should be some kind like this:

function verifyFunction (user, done) { // user = { id: 1};
   // Emulate database fetch result
    var mock = {
       id: 1,
       role: User.ROLE_DEFAULT,
       first_name: 'John',
       last_name: 'Doe'
    };
    done(null, mock);
}

For example if we want test an auth fail situations we shoud use:

 function verifyFunction (user, done) {
    done(new Error('Only authenticated'));
 }

@jakeorr
Copy link

jakeorr commented Jun 13, 2016

Very useful, thanks @mweibel 👍

@mathieu166
Copy link

mathieu166 commented Apr 10, 2017

I'll give some input as well so that others don't waste hours figuring out why after authentication, it gives a 404 on the login url. It is because you must provide a successRedirect so that passport know where to redirect the client once the authentication has pass.

So in passport-mock.js line 14, it should look like that instead:

app.get('/auth/google', passport.authenticate('mock',{successRedirect: '/',failureRedirect: '/login'}));

And thanks to the author for that code, it helps for unit test my app! :)

@disappearer
Copy link

Thank you for this example, it helped a lot. Otherwise, just wanted to point out that it's always going to pass authentication, regardless of StrategyMock constructor options:
this.passAuthentication = options.passAuthentication || true;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment