Unopinionated authentication for express; an alternative to passport.
If your needs are simple and you only have one kind of authentication you can use express-authentication
mixins trivially out of the box.
var express = require('express'),
authentication = require('express-authentication'),
app = express();
app.use(function myauth(req, res, next) {
// provide the data that was used to authenticate the request; if this is
// not set then no attempt to authenticate is registered.
req.challenge = req.get('Authorization');
req.authenticated = req.authentication === 'secret';
// provide the result of the authentication; generally some kind of user
// object on success and some kind of error as to why authentication failed
// otherwise.
if (req.authenticated) {
req.authentication = { user: 'bob' };
} else {
req.authentication = { error: 'INVALID_API_KEY' };
}
// That's it! You're done!
next();
});
app.get('/secret', authentication.required(), function(req, res) {
res.status(200).send('Hello!');
});
If you want to use more than one authentication middleware then use the magic of contextualization.
var express = require('express'),
authentication = require('express-authentication'),
app = express();
var auth = authentication();
// Authentication is just middleware! The middleware must just obey a few rules;
// no need to include another library.
var api = auth.for('api').use(function(req, res, next) {
// provide the data that was used to authenticate the request; if this is
// not set then no attempt to authenticate is registered.
req.challenge = req.get('Authorization');
req.authenticated = req.authentication === 'secret';
// provide the result of the authentication; generally some kind of user
// object on success and some kind of error as to why authentication failed
// otherwise.
if (req.authenticated) {
req.authentication = { user: 'bob' };
} else {
req.authentication = { error: 'INVALID_API_KEY' };
}
// That's it! You're done!
next();
});
var session = auth.for('session').use(function(req, res, next) {
// ...
});
var facebook = auth.for('facebook').use(function(req, res, next) {
// ...
});
// Allow session/api authentication to occur anywhere; that is to say someone
// can provide credentials for either kind of authentication and they will be
// accepted.
app.use(session);
app.use(api);
// Only allow facebook authentication to occur at the /facebook location.
app.use('/facebook', facebook);
// Ensure this route is only authenticated via session
app.get('/session', session.required());
// Allow anything to authenticate against this route
app.get('/any', auth.required());
// Invoke specific middleware when authentication either succeeds or fails
// which is much more powerful than passports `redirect` ability.
app.get('/handlers', api.succeeded(), redirect());
app.get('/handlers', session.succeeded(), redirect());
app.get('/handlers', auth.failed(), redirect());
// Get authentication data from middleware itself
app.get('/any', function(req, res) {
// Get anything that was set
var result = api.of(req);
if (result.authenticated) {
// Use auth.data
}
});
- required - fail the route unless auth succeeded
- succeeded - continue middleware chain only if auth succeeded
- failed - continue middleware chain only if auth failed
- tried - continue middleware chain only if auth tried
- untried - continue middleware chain only if auth untried
// Authentication is just middleware! The middleware must just obey a few rules;
// no need to include another library.
function api(req, res, next) {
// provide the data that was used to authenticate the request; if this is
// not set then no attempt to authenticate is registered. if no data is
// provided but you still wish to register an authentication attempt, set
// this to true.
req.challenge = req.get('Authorization');
// provide the result of the authentication; true if it succeeded, false
// if it did not.
req.authenticated = req.authentication === 'secret';
// provide the metadata of the authentication; generally some kind of user
// object on success and some kind of error as to why authentication failed
// otherwise.
if (req.authenticated) {
req.authentication = { user: 'bob' };
} else {
req.authentication = { error: 'INVALID_API_KEY' };
}
// That's it! You're done!
next();
};
// Let everyone use it.
module.exports = api;
Make sure you include us in your keywords and mark which version of the API you are compatible with in your package.json
!
{
"keywords": [ "express-authentication" ],
"peerDependencies": {
"express-authentication": "^0.3.0"
}
}
Passport is very opinionated. Passport has more strategies available.
express-authentication
an authentication framework; we don't touch your sessions. passport (although possible to use without) pretty much assumes you're going to be using session-based authentication.
Passport strategies must always inherit from a base Strategy
class; they are not middleware themselves.
passport
strategy:
// passport strategy
function SessionStrategy() {
Strategy.call(this);
this.name = 'session';
}
util.inherits(SessionStrategy, Strategy);
SessionStrategy.prototype.authenticate = function(req, options) {
// ...
}
module.exports = SessionStrategy;
express-authentication
middleware:
module.exports = function(req, res, next) {
// ...
}
Authentication and actions from authentication results are tightly coupled in passport. It is not possible to delegate when authentication failure should occur.
passport
delegation:
// passport binds actions
app.get('/login', passport.authenticate('provider', {
successRedirect: '/',
failureRedirect: '/login'
}));
express-authentication
delegation:
// express-authentication lets you do what you want
app.get('/login', provider.succeeded(), redirect('/'))
app.get('/login', provider.failed(), redirect('/login'))