green-jwt
Version:
Node implementation of JSON Web Token (JWT) with support for signatures (JWS), encryption (JWE) and web keys (JWK).
388 lines (325 loc) • 10.4 kB
JavaScript
// Generated by CoffeeScript 1.6.3
(function() {
var HMACSigner, HMACVerifier, JwaAlgorithm, NONE_SIGNER, NoneSigner, NoneVerifier, RSSigner, RSVerifier, crypto, ju, jwa_provider, jwa_table, jwa_verifier, newHMACSigner, newHMACVerifier, newNoneSigner, newNoneVerifier, newRSSigner, newRSVerifier, _ref, _ref1, _ref2, _ref3,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
crypto = require("crypto");
ju = require("./utils");
jwa_table = {
NONE: {
TYPE: "SIGNATURE",
HASH_AL: {}
},
HMAC: {
TYPE: "SIGNATURE",
HASH_AL: {
HS256: "SHA256",
HS384: "SHA384",
HS512: "SHA512"
}
},
RSA: {
TYPE: "SIGNATURE",
HASH_AL: {
RS256: "RSA-SHA256",
RS384: "RSA-SHA384",
RS512: "RSA-SHA512"
}
}
};
JwaAlgorithm = (function() {
function JwaAlgorithm() {}
JwaAlgorithm.prototype.type = function() {
var _ref;
return jwa_table != null ? (_ref = jwa_table[this.alg]) != null ? _ref.TYPE : void 0 : void 0;
};
JwaAlgorithm.prototype.hash = function(alg) {
var _ref;
return jwa_table != null ? (_ref = jwa_table[this.alg]) != null ? _ref.HASH_AL[alg] : void 0 : void 0;
};
return JwaAlgorithm;
})();
NoneSigner = (function(_super) {
__extends(NoneSigner, _super);
function NoneSigner() {
_ref = NoneSigner.__super__.constructor.apply(this, arguments);
return _ref;
}
NoneSigner.prototype.alg = "NONE";
NoneSigner.prototype.update = function(data) {
return this;
};
NoneSigner.prototype.digest = function() {
return "";
};
NoneSigner.prototype.sign = function() {
return this.digest();
};
return NoneSigner;
})(JwaAlgorithm);
NONE_SIGNER = new NoneSigner;
newNoneSigner = function() {
return NONE_SIGNER;
};
NoneVerifier = (function(_super) {
__extends(NoneVerifier, _super);
function NoneVerifier() {
_ref1 = NoneVerifier.__super__.constructor.apply(this, arguments);
return _ref1;
}
NoneVerifier.prototype.alg = "NONE";
NoneVerifier.prototype.verify = function(jwt_req) {
var jwt_claim, jwt_enc_sig, jwt_header, _ref2;
jwt_header = jwt_req != null ? jwt_req.header : void 0;
jwt_claim = jwt_req != null ? jwt_req.claim : void 0;
jwt_enc_sig = jwt_req != null ? (_ref2 = jwt_req.segments) != null ? _ref2[2] : void 0 : void 0;
if (jwt_header.alg !== "none") {
return false;
}
if (jwt_enc_sig) {
return false;
}
return true;
};
return NoneVerifier;
})(JwaAlgorithm);
newNoneVerifier = function() {
return new NoneVerifier;
};
HMACSigner = (function(_super) {
__extends(HMACSigner, _super);
HMACSigner.prototype.alg = "HMAC";
function HMACSigner(alg, key) {
var error;
if (alg == null) {
alg = "HS256";
}
this.key = key;
if (!alg) {
throw Error("A defined algorithm is required.");
}
this.osslAlg = this.hash(alg.toUpperCase());
if (!this.osslAlg) {
throw Error("Algorithm " + this.alg + " is not supported by HMAC.");
}
try {
this.hmac = crypto.createHmac(this.osslAlg, this.key);
} catch (_error) {
error = _error;
throw new Error("HMAC does not support algorithm " + this.alg + " => " + this.osslAlg + "! " + error);
}
}
HMACSigner.prototype.update = function(data) {
if (!this.hmac) {
throw new Error("There is no reference to the hmac object!");
}
this.hmac.update(data);
return this;
};
HMACSigner.prototype.digest = function(encoding) {
if (encoding == null) {
encoding = "base64";
}
if (!this.hmac) {
throw new Error("There is no reference to the hmac object!");
}
return ju.base64urlEscape(this.hmac.digest(encoding));
};
HMACSigner.prototype.sign = function(encoding) {
return this.digest(encoding);
};
return HMACSigner;
})(JwaAlgorithm);
newHMACSigner = function(alg, key) {
return new HMACSigner(alg, key);
};
HMACVerifier = (function(_super) {
__extends(HMACVerifier, _super);
function HMACVerifier() {
_ref2 = HMACVerifier.__super__.constructor.apply(this, arguments);
return _ref2;
}
HMACVerifier.prototype.alg = "HMAC";
HMACVerifier.prototype.verify = function(jwt_req, key) {
var algImpl, signer, _actual_sign, _alg, _claim, _enc_sig, _ref3, _ref4, _ref5, _ref6, _ref7, _typ;
if (!jwt_req) {
throw new Error("jwt request not specified");
}
if (!key) {
throw new Error("key not specified");
}
_typ = jwt_req != null ? (_ref3 = jwt_req.header) != null ? _ref3.typ : void 0 : void 0;
_alg = jwt_req != null ? (_ref4 = jwt_req.header) != null ? _ref4.alg : void 0 : void 0;
_claim = jwt_req != null ? jwt_req.claim : void 0;
_enc_sig = jwt_req != null ? (_ref5 = jwt_req.segments) != null ? _ref5[2] : void 0 : void 0;
if (_typ !== "JWT") {
return false;
}
if (!this.hash(_alg)) {
throw new Error("Hash " + _alg + " is not supported!");
}
if (!_enc_sig) {
return false;
}
algImpl = jwa_provider(_alg);
if (!algImpl) {
return false;
}
signer = algImpl(key);
signer.update("" + ((_ref6 = jwt_req.segments) != null ? _ref6[0] : void 0) + "." + ((_ref7 = jwt_req.segments) != null ? _ref7[1] : void 0));
_actual_sign = signer.sign();
return _actual_sign === _enc_sig;
};
return HMACVerifier;
})(JwaAlgorithm);
newHMACVerifier = function() {
return new HMACVerifier;
};
RSSigner = (function(_super) {
__extends(RSSigner, _super);
RSSigner.prototype.alg = "RSA";
RSSigner.prototype._assertSigner = function() {
if (!this.signer) {
throw Error("Signer is not defined!");
}
};
function RSSigner(alg, key_PEM) {
var error;
if (alg == null) {
alg = "RSA-SHA256";
}
this.key_PEM = key_PEM;
if (!alg) {
throw Error("A defined algorithm is required.");
}
this.osslAlg = this.hash(alg.toUpperCase());
if (!this.osslAlg) {
new Error("Algorithm " + alg + " is not supported by the specification.");
}
try {
this.signer = crypto.createSign(this.osslAlg);
} catch (_error) {
error = _error;
throw new Error("Unable to create a signer with algorithm " + this.osslAlg + "!");
}
}
RSSigner.prototype.update = function(data) {
this._assertSigner();
this.signer.update(data);
return this;
};
RSSigner.prototype.sign = function(format) {
var _enc_sign, _signed;
if (format == null) {
format = "base64";
}
this._assertSigner();
_signed = this.signer.sign(this.key_PEM, format);
_enc_sign = ju.base64urlEscape(_signed);
return _enc_sign;
};
return RSSigner;
})(JwaAlgorithm);
newRSSigner = function(alg, key_PEM) {
return new RSSigner(alg, key_PEM);
};
RSVerifier = (function(_super) {
var _createVerifier;
__extends(RSVerifier, _super);
function RSVerifier() {
_ref3 = RSVerifier.__super__.constructor.apply(this, arguments);
return _ref3;
}
RSVerifier.prototype.alg = "RSA";
_createVerifier = function(alg) {
var error;
try {
return crypto.createVerify(alg);
} catch (_error) {
error = _error;
throw new Error("Unable to create a verifier with algorithm " + alg + "! " + error);
}
};
RSVerifier.prototype.verify = function(jwt_req, public_key) {
var openSSL, _alg, _claim, _enc_sig, _ref4, _ref5, _ref6, _sig, _typ, _verifier;
if (!jwt_req) {
throw new Error("jwt request not specified");
}
if (!public_key) {
throw new Error("public_key not specified");
}
_typ = jwt_req != null ? (_ref4 = jwt_req.header) != null ? _ref4.typ : void 0 : void 0;
_alg = jwt_req != null ? (_ref5 = jwt_req.header) != null ? _ref5.alg : void 0 : void 0;
_claim = jwt_req != null ? jwt_req.claim : void 0;
_enc_sig = jwt_req != null ? (_ref6 = jwt_req.segments) != null ? _ref6[2] : void 0 : void 0;
if (_typ !== "JWT") {
return false;
}
if (!_enc_sig) {
return false;
}
openSSL = this.hash(_alg);
if (!openSSL) {
throw new Error("Hash " + _alg + " is not supported for this JWA " + this.type);
}
_verifier = _createVerifier(openSSL);
if (!_verifier) {
return false;
}
_verifier.update("" + jwt_req.segments[0] + "." + jwt_req.segments[1]);
_sig = ju.base64urlUnescape(_enc_sig);
return _verifier.verify(public_key, _sig, "base64");
};
return RSVerifier;
})(JwaAlgorithm);
newRSVerifier = function() {
return new RSVerifier;
};
module.exports.provider = jwa_provider = function(code) {
var _this = this;
switch (code) {
case "none":
return function() {
return newNoneSigner();
};
case "HS256":
case "HS384":
case "HS512":
return function(key) {
return newHMACSigner(code, key);
};
case "RS256":
case "RS384":
case "RS512":
return function(key) {
return newRSSigner(code, key);
};
case "ES256":
case "ES384":
case "ES512":
return void 0;
default:
return void 0;
}
};
module.exports.verifier = jwa_verifier = function(code) {
switch (code) {
case "none":
return newNoneVerifier();
case "HS256":
case "HS384":
case "HS512":
return newHMACVerifier();
case "RS256":
case "RS384":
case "RS512":
return newRSVerifier();
case "ES256":
case "ES384":
case "ES512":
return void 0;
default:
return void 0;
}
};
}).call(this);