authen
Version:
Authentication tools - signing, tokens, password hashes
148 lines (123 loc) • 4.17 kB
JavaScript
"use strict";
var cookie = require('cookie');
var ops = require('ops');
var HttpAdapter = function (opt_options) {
var options = opt_options || {};
this.cookieOptions = ops.cloneWithDefaults(options.cookie, this.getDefaultCookieOptions());
var cookieNames = options.names && options.names.cookie;
var headerNames = options.names && options.names.header;
this.cookieNames = ops.cloneWithDefaults(cookieNames, this.getDefaultCookieNames());
this.headerNames = ops.cloneWithDefaults(headerNames, this.getDefaultHeaderNames());
this.headerNames.authLower = this.headerNames.auth.toLowerCase();
this.headerNames.expectedLower = this.headerNames.expected.toLowerCase();
};
HttpAdapter.prototype.getDefaultCookieOptions = function () {
return {
httpOnly: true,
secure: false,
domain: null,
path: '/'
};
};
HttpAdapter.prototype.getDefaultCookieNames = function () {
return {
auth: 'auth',
authLimited: 'authTwin'
};
};
HttpAdapter.prototype.getDefaultHeaderNames = function () {
return {
auth: 'X-Auth',
expected: 'X-AuthExpected',
renewal: 'X-AuthRenewal',
renewalIssued: 'X-AuthRenewalIssued',
renewalMaxAge: 'X-AuthRenewalMaxAge'
};
};
HttpAdapter.prototype.extractAuthData = function (req) {
var token = this.getHeaderToken(req);
var additionalToken = null;
var isCsrfProtected = false;
if (token != null) {
isCsrfProtected = true;
additionalToken = this.getCookieToken(req);
}
else {
token = this.getCookieToken(req);
}
var expectedIdentityStr = null;
if (token != null) {
expectedIdentityStr = this.getExpectedIdentityStr(req);
}
return token == null ? null : {
token: token,
additionalToken: additionalToken,
isCsrfProtected: isCsrfProtected,
expectedIdentityStr: expectedIdentityStr
};
};
HttpAdapter.prototype.applyAuthData = function (res, tokenInfo, maxAge, useCookies) {
if (useCookies) {
this.setTokenCookies(res, tokenInfo, maxAge);
}
};
HttpAdapter.prototype.applyRenewal = function (res, renewalTokenInfo, maxAge, useCookies) {
this.setRenewalHeaders(res, renewalTokenInfo, maxAge);
this.applyAuthData(res, renewalTokenInfo, maxAge, useCookies);
};
HttpAdapter.prototype.clearCookies = function (res) {
var expires = new Date(0);
var value = 'del';
this.setCookie(res, this.cookieNames.auth, value, expires);
this.setCookie(res, this.cookieNames.authLimited, value, expires);
};
// internal
// extract
HttpAdapter.prototype.getHeaderToken = function (req) {
return req.headers[this.headerNames.authLower];
};
HttpAdapter.prototype.getCookieToken = function (req) {
return req.cookies != null ? req.cookies[this.cookieNames.auth] : null;
};
HttpAdapter.prototype.getExpectedIdentityStr = function (req) {
var result = null;
var expectedIdentityStr = req.headers[this.headerNames.expectedLower];
if (expectedIdentityStr) {
try {
result = JSON.parse(expectedIdentityStr);
}
catch (err) {
// TODO throw an error instead to be able to respond 400 or something?
result = null;
}
}
return result;
};
// apply
HttpAdapter.prototype.setTokenCookies = function (res, tokenInfo, maxAge) {
var expires = (maxAge == null ? null : new Date(tokenInfo.issued + maxAge));
this.setCookie(res, this.cookieNames.auth, tokenInfo.token, expires, true);
if (tokenInfo.limitedToken != null) {
this.setCookie(res, this.cookieNames.authLimited, tokenInfo.limitedToken, expires);
}
};
HttpAdapter.prototype.setCookie = function (res, name, value, expires, opt_isHttpOnly) {
var options = {
secure: this.cookieOptions.secure,
httpOnly: !!opt_isHttpOnly && this.cookieOptions.httpOnly,
expires: expires,
domain: this.cookieOptions.domain,
path: this.cookieOptions.path
};
res.setHeader('Set-Cookie', cookie.serialize(name, value, options));
};
HttpAdapter.prototype.setRenewalHeaders = function (res, renewalTokenInfo, maxAge) {
if (renewalTokenInfo.token != null) {
res.setHeader(this.headerNames.renewal, renewalTokenInfo.token);
}
res.setHeader(this.headerNames.renewalIssued, renewalTokenInfo.issued.toISOString());
if (maxAge != null) {
res.setHeader(this.headerNames.renewalMaxAge, '' + maxAge);
}
};
module.exports = HttpAdapter;