passport-openam-agco
Version:
Passport strategy to query OpenAM for token_info with Redis cache
123 lines (103 loc) • 3.99 kB
JavaScript
var BasicStrategy = require('passport-http').BasicStrategy,
OAuth2Strategy = require('passport-http-bearer').Strategy,
$http = require('http-as-promised'),
MD5 = require('md5'),
promise = require('bluebird'),
Redis = require('redis');
promise.promisifyAll(Redis.RedisClient.prototype);
promise.promisifyAll(Redis.Multi.prototype);
function _fetchAndCacheUser(options, token, hashedToken) {
return $http.get(options.infoURL + '?access_token=' + token,
{
json: true,
error: false
})
.spread(function cacheValidResponse(res, body) {
var user;
if (!body || !body.agcoUUID || !body.expires_in) return false;
// cache valid user
user = {
sub: body.agcoUUID,
token: body
};
return options.redis.multi()
.set(hashedToken, JSON.stringify(user))
.expire(hashedToken, body.expires_in)
.execAsync().then(function () {
return user;
});
});
}
function createBasicStrategy(options) {
var redis = Redis.createClient(options.redis);
return new BasicStrategy(function(username, password, done) {
var header = username + ':' + password,
hashedHeader = basicKey(MD5(header)),
URL = options.openAMBaseURL,
infoURL = options.openAMInfoURL,
scopes = options.scope.join(' ');
return getRedis(redis, hashedHeader)
.then(function(cachedUser) {
if (!cachedUser) {
// use username and password to get a token
return $http.post(URL, {
form: {
client_id: options.client_id,
client_secret: options.client_secret,
grant_type: 'password',
username: username,
password: password,
scope: scopes
},
error: true,
json:true
})
.spread(function useTokentoGetAndCacheUser(res, body) {
if (!body || !body.access_token) return false;
return _fetchAndCacheUser({ infoURL: infoURL, redis: redis }, body.access_token, hashedHeader);
});
}
return JSON.parse(cachedUser);
})
.then(function returnUser(authedUser) {
return done(null, authedUser);
})
.catch(function invalidate(err) {
console.error('[BasicStrategy]:', err)
return done(null, false)
});
});
}
function createOauth2Strategy(options) {
var redis = Redis.createClient(options.redis);
return new OAuth2Strategy(function verify(token, done) {
var hashedToken = oauth2Key(MD5(token));
return getRedis(redis, hashedToken)
.then(function checkCache(cachedUser) {
if (!cachedUser) return _fetchAndCacheUser({ infoURL: options.openAMInfoURL, redis: redis }, token, hashedToken);
return JSON.parse(cachedUser);
})
.then(function returnUser(authedUser) {
return done(null, authedUser);
})
.catch(function invalidateAllErrors(err) {
console.error('[Oauth2Strategy]:', err)
return done(err, false);
});
});
}
function getRedis(redis, key) {
return redis.getAsync(key);
}
function basicKey(md5) {
return md5 + "-basic";
}
function oauth2Key(md5) {
return md5 + "-oauth2";
}
module.exports = {
basicKey: basicKey,
oauth2Key: oauth2Key,
basic: createBasicStrategy,
oauth2: createOauth2Strategy
};