From 5904561478384ca00cc4fe3d9a58dd48cb1ec40a Mon Sep 17 00:00:00 2001 From: Robin Date: Sat, 1 Oct 2016 18:20:22 +0200 Subject: [PATCH] add typed error handling --- README.md | 25 +++ errors.js | 68 ++++++++ index.js | 69 ++++----- properties.json | 11 -- test/builder.js | 11 +- test/errors.js | 395 +++++++++++++++++++++++++++++++++++++++++++++++ test/jwt.js | 6 +- test/rsa.js | 6 +- test/verifier.js | 36 ++--- 9 files changed, 547 insertions(+), 80 deletions(-) create mode 100644 errors.js delete mode 100644 properties.json create mode 100644 test/errors.js diff --git a/README.md b/README.md index b0130c0..ebd9336 100644 --- a/README.md +++ b/README.md @@ -219,6 +219,31 @@ jwt.setNotbefore(); // Remove the exp claim ``` +## Error Handling + +If an error occurs then one of the following error types will either be thrown +or passed as the first argument in a callback. + +Type | Description +----------------------------------------|-------------------------------------- +JwtError | Base type. All errors implement this. +JwtParseError | Jwt cannot be parsed. +UnsupportedSigningAlgorithmJwtError | Unsupported signing algorithm. +SigningKeyRequiredJwtError | Signing key is required. +NotActiveJwtParseError | Jwt not active. +ExpiredJwtParseError | Jwt is expired. +SignatureAlgorithmMismatchJwtParseError | Unexpected signature algorithm. +SignatureMismatchJwtParseError | Signature verification failed. + +To handle a specific error scenario, simply compare the instance of the error received to one of +the error types above, as shown in the example below: + +```javascript +if (err instanceof nJwt.JwtParseError) { + console.log('Unable to parse the provided jwt.'); +} +``` + ## Supported Algorithms "alg" Value | Algorithm used diff --git a/errors.js b/errors.js new file mode 100644 index 0000000..204e21d --- /dev/null +++ b/errors.js @@ -0,0 +1,68 @@ +var util = require('util'); + +function JwtError(message) { + this.name = 'JwtError'; + this.message = this.userMessage = message; +} +util.inherits(JwtError, Error); + +function JwtParseError(jwtString, parsedHeader, parsedBody, innerError) { + this.name = 'JwtParseError'; + this.message = this.userMessage = 'Jwt cannot be parsed'; + this.jwtString = jwtString; + this.parsedHeader = parsedHeader; + this.parsedBody = parsedBody; + this.innerError = innerError; +} +util.inherits(JwtParseError, JwtError); + +function UnsupportedSigningAlgorithmJwtError() { + UnsupportedSigningAlgorithmJwtError.super_.call(this, 'Unsupported signing algorithm'); + this.name = 'UnsupportedSigningAlgorithmJwtError'; +} +util.inherits(UnsupportedSigningAlgorithmJwtError, JwtError); + +function SigningKeyRequiredJwtError() { + SigningKeyRequiredJwtError.super_.call(this, 'Signing key is required'); + this.name = 'SigningKeyRequiredJwtError'; +} +util.inherits(SigningKeyRequiredJwtError, JwtError); + +function NotActiveJwtParseError(jwtString, parsedHeader, parsedBody) { + NotActiveJwtParseError.super_.call(this, jwtString, parsedHeader, parsedBody); + this.name = 'NotActiveJwtParseError'; + this.message = this.userMessage = 'Jwt not active'; +} +util.inherits(NotActiveJwtParseError, JwtParseError); + +function ExpiredJwtParseError(jwtString, parsedHeader, parsedBody) { + ExpiredJwtParseError.super_.call(this, jwtString, parsedHeader, parsedBody); + this.name = 'ExpiredJwtParseError'; + this.message = this.userMessage = 'Jwt is expired'; +} +util.inherits(ExpiredJwtParseError, JwtParseError); + +function SignatureAlgorithmMismatchJwtParseError(jwtString, parsedHeader, parsedBody) { + SignatureAlgorithmMismatchJwtParseError.super_.call(this, jwtString, parsedHeader, parsedBody); + this.name = 'SignatureAlgorithmMismatchJwtParseError'; + this.message = this.userMessage = 'Unexpected signature algorithm'; +} +util.inherits(SignatureAlgorithmMismatchJwtParseError, JwtParseError); + +function SignatureMismatchJwtParseError(jwtString, parsedHeader, parsedBody, innerError) { + SignatureMismatchJwtParseError.super_.call(this, jwtString, parsedHeader, parsedBody, innerError); + this.name = 'SignatureMismatchJwtParseError'; + this.message = this.userMessage = 'Signature verification failed'; +} +util.inherits(SignatureMismatchJwtParseError, JwtParseError); + +module.exports = { + JwtError: JwtError, + JwtParseError: JwtParseError, + UnsupportedSigningAlgorithmJwtError: UnsupportedSigningAlgorithmJwtError, + SigningKeyRequiredJwtError: SigningKeyRequiredJwtError, + NotActiveJwtParseError: NotActiveJwtParseError, + ExpiredJwtParseError: ExpiredJwtParseError, + SignatureAlgorithmMismatchJwtParseError: SignatureAlgorithmMismatchJwtParseError, + SignatureMismatchJwtParseError: SignatureMismatchJwtParseError +}; \ No newline at end of file diff --git a/index.js b/index.js index 87246ea..1211f6a 100644 --- a/index.js +++ b/index.js @@ -1,10 +1,9 @@ 'use strict'; -var util = require('util'); var uuid = require('uuid'); var crypto = require('crypto'); var ecdsaSigFormatter = require('ecdsa-sig-formatter'); -var properties = require('./properties.json'); +var errors = require('./errors'); var algCryptoMap = { HS256: 'SHA256', @@ -68,22 +67,6 @@ function handleError(cb,err,value){ } } -function JwtError(message) { - this.name = 'JwtError'; - this.message = this.userMessage = message; -} -util.inherits(JwtError, Error); - -function JwtParseError(message,jwtString,parsedHeader,parsedBody,innerError) { - this.name = 'JwtParseError'; - this.message = this.userMessage = message; - this.jwtString = jwtString; - this.parsedHeader = parsedHeader; - this.parsedBody = parsedBody; - this.innerError = innerError; -} -util.inherits(JwtParseError, Error); - function JwtBody(claims){ if(!(this instanceof JwtBody)){ return new JwtBody(claims); @@ -194,7 +177,7 @@ Jwt.prototype.setSigningKey = function setSigningKey(key) { }; Jwt.prototype.setSigningAlgorithm = function setSigningAlgorithm(alg) { if(!this.isSupportedAlg(alg)){ - throw new JwtError(properties.errors.UNSUPPORTED_SIGNING_ALG); + throw new errors.UnsupportedSigningAlgorithmJwtError(); } this.header.alg = alg; return this; @@ -207,7 +190,7 @@ Jwt.prototype.sign = function sign(payload, algorithm, cryptoInput) { var signingType = algTypeMap[algorithm]; if (!cryptoAlgName) { - throw new JwtError(properties.errors.UNSUPPORTED_SIGNING_ALG); + throw new errors.UnsupportedSigningAlgorithmJwtError(); } if (signingType === 'hmac') { @@ -234,12 +217,13 @@ Jwt.prototype.compact = function compact() { segments.push(this.body.compact()); if(this.header.alg !== 'none'){ - if (this.signingKey) { - this.signature = this.sign(segments.join('.'), this.header.alg, this.signingKey); - segments.push(this.signature); - }else{ - throw new Error(properties.errors.SIGNING_KEY_REQUIRED); + if (!this.signingKey) { + throw new errors.SigningKeyRequiredJwtError(); } + + this.signature = this.sign(segments.join('.'), this.header.alg, this.signingKey); + + segments.push(this.signature); } return segments.join('.'); @@ -278,7 +262,7 @@ Parser.prototype.parse = function parse(jwtString,cb){ var signature; if(segments.length<2 || segments.length>3){ - return done(new JwtParseError(properties.errors.PARSE_ERROR,jwtString,null,null)); + return done(new errors.JwtParseError(jwtString)); } var header = this.safeJsonParse(segments[0]); @@ -290,10 +274,10 @@ Parser.prototype.parse = function parse(jwtString,cb){ } if(header instanceof Error){ - return done(new JwtParseError(properties.errors.PARSE_ERROR,jwtString,null,null,header)); + return done(new errors.JwtParseError(jwtString, null, null, header)); } if(body instanceof Error){ - return done(new JwtParseError(properties.errors.PARSE_ERROR,jwtString,header,null,body)); + return done(new errors.JwtParseError(jwtString, header, null, body)); } var jwt = new Jwt(body, false); jwt.setSigningAlgorithm(header.alg); @@ -312,7 +296,7 @@ function Verifier(){ } Verifier.prototype.setSigningAlgorithm = function setSigningAlgorithm(alg) { if(!this.isSupportedAlg(alg)){ - throw new JwtError(properties.errors.UNSUPPORTED_SIGNING_ALG); + throw new errors.UnsupportedSigningAlgorithmJwtError(); } this.signingAlgorithm = alg; return this; @@ -342,15 +326,15 @@ Verifier.prototype.verify = function verify(jwtString,cb){ var signingType = algTypeMap[header.alg]; if (header.alg !== this.signingAlgorithm) { - return done(new JwtParseError(properties.errors.SIGNATURE_ALGORITHM_MISMTACH,jwtString,header,body)); + return done(new errors.SignatureAlgorithmMismatchJwtParseError(jwtString, header, body)); } if (jwt.isExpired()) { - return done(new JwtParseError(properties.errors.EXPIRED,jwtString,header,body)); + return done(new errors.ExpiredJwtParseError(jwtString, header, body)); } if (jwt.isNotBefore()) { - return done(new JwtParseError(properties.errors.NOT_ACTIVE,jwtString,header,body)); + return done(new errors.NotActiveJwtParseError(jwtString, header, body)); } var digstInput = jwt.verificationInput; @@ -371,7 +355,7 @@ Verifier.prototype.verify = function verify(jwtString,cb){ try { unescapedSignature = ecdsaSigFormatter.joseToDer(signature, header.alg); } catch (err) { - return done(new JwtParseError(properties.errors.SIGNATURE_MISMTACH,jwtString,header,body,err)); + return done(new errors.SignatureMismatchJwtParseError(jwtString, header, body, err)); } } else { signatureType = 'base64'; @@ -392,7 +376,7 @@ Verifier.prototype.verify = function verify(jwtString,cb){ newJwt.header = new JwtHeader(header); if (!verified) { - return done(new JwtParseError(properties.errors.SIGNATURE_MISMTACH,jwtString,header,body)); + return done(new errors.SignatureMismatchJwtParseError(jwtString, header, body)); } return done(null, newJwt); @@ -441,15 +425,22 @@ var jwtLib = { }else{ jwt = new Jwt(claims); } - if(alg!=='none' && !secret){ - throw new Error(properties.errors.SIGNING_KEY_REQUIRED); - }else{ - jwt.setSigningAlgorithm(args.length===3 ? alg : 'HS256'); - jwt.setSigningKey(secret); + + if(alg !== 'none' && !secret){ + throw new errors.SigningKeyRequiredJwtError(); } + + jwt.setSigningAlgorithm(args.length===3 ? alg : 'HS256'); + jwt.setSigningKey(secret); jwt.setExpiration((nowEpochSeconds() + (60*60))*1000); // one hour + return jwt; } }; +// Copy errors onto export object. +for (var key in errors) { + jwtLib[key] = errors[key]; +} + module.exports = jwtLib; diff --git a/properties.json b/properties.json deleted file mode 100644 index 27045e1..0000000 --- a/properties.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "errors": { - "PARSE_ERROR": "Jwt cannot be parsed", - "EXPIRED": "Jwt is expired", - "UNSUPPORTED_SIGNING_ALG": "Unsupported signing algorithm", - "SIGNING_KEY_REQUIRED": "Signing key is required", - "SIGNATURE_MISMTACH": "Signature verification failed", - "SIGNATURE_ALGORITHM_MISMTACH": "Unexpected signature algorithm", - "NOT_ACTIVE": "Jwt not active" - } -} diff --git a/test/builder.js b/test/builder.js index c1a20d2..a14fbb6 100644 --- a/test/builder.js +++ b/test/builder.js @@ -3,7 +3,7 @@ var assert = require('chai').assert; var nJwt = require('../'); var uuid = require('uuid'); -var properties = require('../properties.json'); +var errors = require('../errors'); describe('Jwt()',function(){ describe('signWith()',function(){ @@ -11,7 +11,7 @@ describe('Jwt()',function(){ it('should throw',function(){ assert.throws(function(){ new nJwt.Jwt().setSigningAlgorithm('unsupported'); - },properties.errors.UNSUPPORTED_SIGNING_ALG); + },errors.UnsupportedSigningAlgorithmJwtError); }); }); }); @@ -20,10 +20,10 @@ describe('Jwt()',function(){ describe('create()',function(){ - it('should throw SIGNING_KEY_REQUIRED if passed no options',function(){ + it('should throw UnsupportedSigningAlgorithmJwtError if passed no options',function(){ assert.throws(function(){ nJwt.create(); - },properties.errors.SIGNING_KEY_REQUIRED); + },errors.SigningKeyRequiredJwtError); }); it('should create a default token if the scret is the only value',function(){ @@ -33,7 +33,7 @@ describe('create()',function(){ it('should throw if using defaults without a secret key',function(){ assert.throws(function(){ nJwt.create({}); - },properties.errors.SIGNING_KEY_REQUIRED); + },errors.SigningKeyRequiredJwtError); }); it('should not throw if none is specified when omitting the key',function(){ @@ -43,7 +43,6 @@ describe('create()',function(){ }); describe('with a signing key',function(){ - it('should return a JWT',function(){ assert(nJwt.create({},uuid()) instanceof nJwt.Jwt); }); diff --git a/test/errors.js b/test/errors.js new file mode 100644 index 0000000..4cc4614 --- /dev/null +++ b/test/errors.js @@ -0,0 +1,395 @@ +var assert = require('chai').assert; +var errors = require('../errors'); + +describe('Errors', function () { + describe('JwtError', function () { + describe('when creating a new JwtError instance', function () { + it('should be an instance of Error', function () { + var error = new errors.JwtError(); + assert.instanceOf(error, Error); + }); + + it('should be an instance of JwtError', function () { + var error = new errors.JwtError(); + assert.instanceOf(error, errors.JwtError); + }); + + it('should set the message property', function () { + var fakeMessage = 'c9b9ec16-8c6a-41b8-ba12-eec5bff7d437'; + var error = new errors.JwtError(fakeMessage); + assert.equal(error.message, fakeMessage); + }); + + it('should set the userMessage property', function () { + var fakeMessage = '36e4439b-8036-4ce6-af8c-434e6343fca1'; + var error = new errors.JwtError(fakeMessage); + assert.equal(error.userMessage, fakeMessage); + }); + + it('should set the name property', function () { + var error = new errors.JwtError(); + assert.equal(error.name, 'JwtError'); + }); + + it('should set the message property', function () { + var fakeMessage = '9ac2400c-22f7-413c-8777-97f2ab2ab266'; + var error = new errors.JwtError(fakeMessage); + assert.equal(error.message, fakeMessage); + }); + }); + }); + + describe('UnsupportedSigningAlgorithmJwtError', function () { + describe('when creating a new UnsupportedSigningAlgorithmJwtError instance', function () { + it('should be an instance of Error', function () { + var error = new errors.UnsupportedSigningAlgorithmJwtError(); + assert.instanceOf(error, Error); + }); + + it('should be an instance of JwtError', function () { + var error = new errors.UnsupportedSigningAlgorithmJwtError(); + assert.instanceOf(error, errors.JwtError); + }); + + it('should be an instance of UnsupportedSigningAlgorithmJwtError', function () { + var error = new errors.UnsupportedSigningAlgorithmJwtError(); + assert.instanceOf(error, errors.UnsupportedSigningAlgorithmJwtError); + }); + + it('should set the name property', function () { + var error = new errors.UnsupportedSigningAlgorithmJwtError(); + assert.equal(error.name, 'UnsupportedSigningAlgorithmJwtError'); + }); + + it('should set the message property', function () { + var error = new errors.UnsupportedSigningAlgorithmJwtError(); + assert.equal(error.message, 'Unsupported signing algorithm'); + }); + + it('should set the userMessage property', function () { + var error = new errors.UnsupportedSigningAlgorithmJwtError(); + assert.equal(error.userMessage, 'Unsupported signing algorithm'); + }); + }); + }); + + describe('SigningKeyRequiredJwtError', function () { + describe('when creating a new SigningKeyRequiredJwtError instance', function () { + it('should be an instance of Error', function () { + var error = new errors.SigningKeyRequiredJwtError(); + assert.instanceOf(error, Error); + }); + + it('should be an instance of JwtError', function () { + var error = new errors.SigningKeyRequiredJwtError(); + assert.instanceOf(error, errors.JwtError); + }); + + it('should be an instance of SigningKeyRequiredJwtError', function () { + var error = new errors.SigningKeyRequiredJwtError(); + assert.instanceOf(error, errors.SigningKeyRequiredJwtError); + }); + + it('should set the name property', function () { + var error = new errors.SigningKeyRequiredJwtError(); + assert.equal(error.name, 'SigningKeyRequiredJwtError'); + }); + + it('should set the message property', function () { + var error = new errors.SigningKeyRequiredJwtError(); + assert.equal(error.message, 'Signing key is required'); + }); + + it('should set the userMessage property', function () { + var error = new errors.SigningKeyRequiredJwtError(); + assert.equal(error.userMessage, 'Signing key is required'); + }); + }); + }); + + describe('JwtParseError', function () { + describe('when creating a new JwtParseError instance', function () { + it('should be an instance of Error', function () { + var error = new errors.JwtParseError(); + assert.instanceOf(error, Error); + }); + + it('should be an instance of JwtError', function () { + var error = new errors.JwtParseError(); + assert.instanceOf(error, errors.JwtError); + }); + + it('should be an instance of JwtParseError', function () { + var error = new errors.JwtParseError(); + assert.instanceOf(error, errors.JwtParseError); + }); + + it('should set the name property', function () { + var error = new errors.JwtParseError(); + assert.equal(error.name, 'JwtParseError'); + }); + + it('should set the message property', function () { + var error = new errors.JwtParseError(); + assert.equal(error.message, 'Jwt cannot be parsed'); + }); + + it('should set the userMessage property', function () { + var error = new errors.JwtParseError(); + assert.equal(error.userMessage, 'Jwt cannot be parsed'); + }); + + it('should set the jwtString property', function () { + var fakeJwtString = 'c23a1805-a8de-4829-aa0e-5977fe7e1447'; + var error = new errors.JwtParseError(fakeJwtString); + assert.equal(error.jwtString, fakeJwtString); + }); + + it('should set the parsedHeader property', function () { + var fakeParsedHeader = '6764e3a7-ea19-49e7-82e8-7f1e9bbf5ccf'; + var error = new errors.JwtParseError(null, fakeParsedHeader); + assert.equal(error.parsedHeader, fakeParsedHeader); + }); + + it('should set the parsedBody property', function () { + var fakeParsedBody = '938fd5d9-72e8-41a7-941a-3df0bcfa88cb'; + var error = new errors.JwtParseError(null, null, fakeParsedBody); + assert.equal(error.parsedBody, fakeParsedBody); + }); + + it('should set the innerError property', function () { + var fakeFnnerError = '07bee824-a6a6-45b5-b844-42407466adc7'; + var error = new errors.JwtParseError(null, null, null, fakeFnnerError); + assert.equal(error.innerError, fakeFnnerError); + }); + }); + }); + + describe('NotActiveJwtParseError', function () { + describe('when creating a new NotActiveJwtParseError instance', function () { + it('should be an instance of Error', function () { + var error = new errors.NotActiveJwtParseError(); + assert.instanceOf(error, Error); + }); + + it('should be an instance of JwtError', function () { + var error = new errors.NotActiveJwtParseError(); + assert.instanceOf(error, errors.JwtError); + }); + + it('should be an instance of JwtParseError', function () { + var error = new errors.NotActiveJwtParseError(); + assert.instanceOf(error, errors.JwtParseError); + }); + + it('should be an instance of NotActiveJwtParseError', function () { + var error = new errors.NotActiveJwtParseError(); + assert.instanceOf(error, errors.NotActiveJwtParseError); + }); + + it('should set the name property', function () { + var error = new errors.NotActiveJwtParseError(); + assert.equal(error.name, 'NotActiveJwtParseError'); + }); + + it('should set the message property', function () { + var error = new errors.NotActiveJwtParseError(); + assert.equal(error.message, 'Jwt not active'); + }); + + it('should set the userMessage property', function () { + var error = new errors.NotActiveJwtParseError(); + assert.equal(error.userMessage, 'Jwt not active'); + }); + + it('should set the jwtString property', function () { + var fakeJwtString = 'c23a1805-a8de-4829-aa0e-5977fe7e1447'; + var error = new errors.NotActiveJwtParseError(fakeJwtString); + assert.equal(error.jwtString, fakeJwtString); + }); + + it('should set the parsedHeader property', function () { + var fakeParsedHeader = '6764e3a7-ea19-49e7-82e8-7f1e9bbf5ccf'; + var error = new errors.NotActiveJwtParseError(null, fakeParsedHeader); + assert.equal(error.parsedHeader, fakeParsedHeader); + }); + + it('should set the parsedBody property', function () { + var fakeParsedBody = '938fd5d9-72e8-41a7-941a-3df0bcfa88cb'; + var error = new errors.NotActiveJwtParseError(null, null, fakeParsedBody); + assert.equal(error.parsedBody, fakeParsedBody); + }); + }); + }); + + describe('ExpiredJwtParseError', function () { + describe('when creating a new ExpiredJwtParseError instance', function () { + it('should be an instance of Error', function () { + var error = new errors.ExpiredJwtParseError(); + assert.instanceOf(error, Error); + }); + + it('should be an instance of JwtError', function () { + var error = new errors.ExpiredJwtParseError(); + assert.instanceOf(error, errors.JwtError); + }); + + it('should be an instance of JwtParseError', function () { + var error = new errors.ExpiredJwtParseError(); + assert.instanceOf(error, errors.JwtParseError); + }); + + it('should be an instance of ExpiredJwtParseError', function () { + var error = new errors.ExpiredJwtParseError(); + assert.instanceOf(error, errors.ExpiredJwtParseError); + }); + + it('should set the name property', function () { + var error = new errors.ExpiredJwtParseError(); + assert.equal(error.name, 'ExpiredJwtParseError'); + }); + + it('should set the message property', function () { + var error = new errors.ExpiredJwtParseError(); + assert.equal(error.message, 'Jwt is expired'); + }); + + it('should set the userMessage property', function () { + var error = new errors.ExpiredJwtParseError(); + assert.equal(error.userMessage, 'Jwt is expired'); + }); + + it('should set the jwtString property', function () { + var fakeJwtString = 'c23a1805-a8de-4829-aa0e-5977fe7e1447'; + var error = new errors.ExpiredJwtParseError(fakeJwtString); + assert.equal(error.jwtString, fakeJwtString); + }); + + it('should set the parsedHeader property', function () { + var fakeParsedHeader = '6764e3a7-ea19-49e7-82e8-7f1e9bbf5ccf'; + var error = new errors.ExpiredJwtParseError(null, fakeParsedHeader); + assert.equal(error.parsedHeader, fakeParsedHeader); + }); + + it('should set the parsedBody property', function () { + var fakeParsedBody = '938fd5d9-72e8-41a7-941a-3df0bcfa88cb'; + var error = new errors.ExpiredJwtParseError(null, null, fakeParsedBody); + assert.equal(error.parsedBody, fakeParsedBody); + }); + }); + }); + + describe('SignatureAlgorithmMismatchJwtParseError', function () { + describe('when creating a new SignatureAlgorithmMismatchJwtParseError instance', function () { + it('should be an instance of Error', function () { + var error = new errors.SignatureAlgorithmMismatchJwtParseError(); + assert.instanceOf(error, Error); + }); + + it('should be an instance of JwtError', function () { + var error = new errors.SignatureAlgorithmMismatchJwtParseError(); + assert.instanceOf(error, errors.JwtError); + }); + + it('should be an instance of JwtParseError', function () { + var error = new errors.SignatureAlgorithmMismatchJwtParseError(); + assert.instanceOf(error, errors.JwtParseError); + }); + + it('should be an instance of SignatureAlgorithmMismatchJwtParseError', function () { + var error = new errors.SignatureAlgorithmMismatchJwtParseError(); + assert.instanceOf(error, errors.SignatureAlgorithmMismatchJwtParseError); + }); + + it('should set the name property', function () { + var error = new errors.SignatureAlgorithmMismatchJwtParseError(); + assert.equal(error.name, 'SignatureAlgorithmMismatchJwtParseError'); + }); + + it('should set the message property', function () { + var error = new errors.SignatureAlgorithmMismatchJwtParseError(); + assert.equal(error.message, 'Unexpected signature algorithm'); + }); + + it('should set the userMessage property', function () { + var error = new errors.SignatureAlgorithmMismatchJwtParseError(); + assert.equal(error.userMessage, 'Unexpected signature algorithm'); + }); + + it('should set the jwtString property', function () { + var fakeJwtString = 'c23a1805-a8de-4829-aa0e-5977fe7e1447'; + var error = new errors.SignatureAlgorithmMismatchJwtParseError(fakeJwtString); + assert.equal(error.jwtString, fakeJwtString); + }); + + it('should set the parsedHeader property', function () { + var fakeParsedHeader = '6764e3a7-ea19-49e7-82e8-7f1e9bbf5ccf'; + var error = new errors.SignatureAlgorithmMismatchJwtParseError(null, fakeParsedHeader); + assert.equal(error.parsedHeader, fakeParsedHeader); + }); + + it('should set the parsedBody property', function () { + var fakeParsedBody = '938fd5d9-72e8-41a7-941a-3df0bcfa88cb'; + var error = new errors.SignatureAlgorithmMismatchJwtParseError(null, null, fakeParsedBody); + assert.equal(error.parsedBody, fakeParsedBody); + }); + }); + }); + + describe('SignatureMismatchJwtParseError', function () { + describe('when creating a new SignatureMismatchJwtParseError instance', function () { + it('should be an instance of Error', function () { + var error = new errors.SignatureMismatchJwtParseError(); + assert.instanceOf(error, Error); + }); + + it('should be an instance of JwtError', function () { + var error = new errors.SignatureMismatchJwtParseError(); + assert.instanceOf(error, errors.JwtError); + }); + + it('should be an instance of JwtParseError', function () { + var error = new errors.SignatureMismatchJwtParseError(); + assert.instanceOf(error, errors.JwtParseError); + }); + + it('should be an instance of SignatureMismatchJwtParseError', function () { + var error = new errors.SignatureMismatchJwtParseError(); + assert.instanceOf(error, errors.SignatureMismatchJwtParseError); + }); + + it('should set the name property', function () { + var error = new errors.SignatureMismatchJwtParseError(); + assert.equal(error.name, 'SignatureMismatchJwtParseError'); + }); + + it('should set the message property', function () { + var error = new errors.SignatureMismatchJwtParseError(); + assert.equal(error.message, 'Signature verification failed'); + }); + + it('should set the userMessage property', function () { + var error = new errors.SignatureMismatchJwtParseError(); + assert.equal(error.userMessage, 'Signature verification failed'); + }); + + it('should set the jwtString property', function () { + var fakeJwtString = 'c23a1805-a8de-4829-aa0e-5977fe7e1447'; + var error = new errors.SignatureMismatchJwtParseError(fakeJwtString); + assert.equal(error.jwtString, fakeJwtString); + }); + + it('should set the parsedHeader property', function () { + var fakeParsedHeader = '6764e3a7-ea19-49e7-82e8-7f1e9bbf5ccf'; + var error = new errors.SignatureMismatchJwtParseError(null, fakeParsedHeader); + assert.equal(error.parsedHeader, fakeParsedHeader); + }); + + it('should set the parsedBody property', function () { + var fakeParsedBody = '938fd5d9-72e8-41a7-941a-3df0bcfa88cb'; + var error = new errors.SignatureMismatchJwtParseError(null, null, fakeParsedBody); + assert.equal(error.parsedBody, fakeParsedBody); + }); + }); + }); +}); \ No newline at end of file diff --git a/test/jwt.js b/test/jwt.js index cecbfb5..eecaf96 100644 --- a/test/jwt.js +++ b/test/jwt.js @@ -1,7 +1,7 @@ var assert = require('chai').assert; var nJwt = require('../'); var uuid = require('uuid'); -var properties = require('../properties.json'); +var errors = require('../errors'); describe('Jwt',function() { it('should construct itself if called without new',function(){ @@ -79,7 +79,7 @@ describe('Jwt',function() { it('should throw if you specify an alg but not a key',function(){ assert.throws(function(){ nJwt.Jwt().setSigningAlgorithm('HS256').compact(); - },properties.errors.SIGNING_KEY_REQUIRED); + },errors.SigningKeyRequiredJwtError); }); }); @@ -87,7 +87,7 @@ describe('Jwt',function() { it('should throw if you give it an unknown algoritm',function(){ assert.throws(function(){ nJwt.Jwt().sign('hello'); - },properties.errors.UNSUPPORTED_SIGNING_ALG); + },errors.UnsupportedSigningAlgorithmJwtError); }); }); describe('.toString()',function(){ diff --git a/test/rsa.js b/test/rsa.js index 5c8802d..b4f34ec 100644 --- a/test/rsa.js +++ b/test/rsa.js @@ -2,7 +2,7 @@ var assert = require('chai').assert; var nJwt = require('../'); -var properties = require('../properties.json'); +var errors = require('../errors'); var fs = require('fs'); var path = require('path'); @@ -82,9 +82,9 @@ describe('a token that is signed with an RSA public key but header alg of HS256' }); }); - it('should return SIGNATURE_ALGORITHM_MISMTACH error',function(){ + it('should return SignatureAlgorithmMismatchJwtParseError error',function(){ assert.isNotNull(result[0],'An error was not returned'); - assert.equal(result[0].message,properties.errors.SIGNATURE_ALGORITHM_MISMTACH); + assert.instanceOf(result[0],errors.SignatureAlgorithmMismatchJwtParseError); }); }); diff --git a/test/verifier.js b/test/verifier.js index de3fd01..ba87f6e 100644 --- a/test/verifier.js +++ b/test/verifier.js @@ -5,7 +5,7 @@ var secureRandom = require('secure-random'); var assert = require('chai').assert; var nJwt = require('../'); -var properties = require('../properties.json'); +var errors = require('../errors'); describe('Verifier',function(){ it('should construct itself if called without new',function(){ @@ -16,10 +16,10 @@ describe('Verifier',function(){ describe('Verifier().setSigningAlgorithm() ',function(){ describe('if called with an unsupported algorithm',function(){ - it('should throw UNSUPPORTED_SIGNING_ALG',function(){ + it('should throw UnsupportedSigningAlgorithmJwtError',function(){ assert.throws(function(){ new nJwt.Verifier().setSigningAlgorithm('unsupported'); - },properties.errors.UNSUPPORTED_SIGNING_ALG); + },errors.UnsupportedSigningAlgorithmJwtError); }); }); @@ -55,14 +55,14 @@ describe('.verify()',function(){ .compact(); assert.throws(function(){ nJwt.verify(token); - },properties.errors.SIGNATURE_ALGORITHM_MISMTACH); + },errors.SignatureAlgorithmMismatchJwtParseError); }); }); it('should return PARSE_ERROR if the header is not JSON',function(){ assert.throws(function(){ nJwt.verify("noavalidheader.notavalidbody"); - },properties.errors.PARSE_ERROR); + },errors.JwtParseError); }); it('should give me the original string on the parse error object',function(done){ @@ -77,7 +77,7 @@ describe('.verify()',function(){ var header = nJwt.JwtHeader({type:'JWT',alg:'HS256'}).compact(); assert.throws(function(){ nJwt.verify(header+".notavalidbody"); - },properties.errors.PARSE_ERROR); + },errors.JwtParseError); }); it('should give me the parsed header on the error object if the body fails',function(done){ @@ -109,7 +109,7 @@ describe('Verifier().verify() ',function(){ assert.throws(function(){ verifiedToken = verifier.verify('invalid token'); - },properties.errors.PARSE_ERROR); + },errors.JwtParseError); }); @@ -121,7 +121,7 @@ describe('Verifier().verify() ',function(){ assert.equal(err.jwtString,token); assert.equal(err.parsedHeader.alg,jwt.header.alg); assert.equal(err.parsedBody.expiredToken,jwt.body.expiredToken); - assert.equal(err.userMessage,properties.errors.EXPIRED); + assert.instanceOf(err,errors.ExpiredJwtParseError); done(); }); }); @@ -134,7 +134,7 @@ describe('Verifier().verify() ',function(){ assert.equal(err.jwtString,token); assert.equal(err.parsedHeader.alg,jwt.header.alg); assert.equal(err.parsedBody.notActiveToken,jwt.body.notActiveToken); - assert.equal(err.userMessage,properties.errors.NOT_ACTIVE); + assert.instanceOf(err,errors.NotActiveJwtParseError); done(); }); }); @@ -187,7 +187,7 @@ describe('Verifier().verify() ',function(){ it('should return EXPIRED',function(){ assert.isNotNull(result[0],'An error was not returned'); - assert.equal(result[0].userMessage,properties.errors.EXPIRED); + assert.instanceOf(result[0],errors.ExpiredJwtParseError); }); }); @@ -206,7 +206,7 @@ describe('Verifier().verify() ',function(){ it('should return NOT_ACTIVE',function(){ assert.isNotNull(result[0],'An error was not returned'); - assert.equal(result[0].userMessage,properties.errors.NOT_ACTIVE); + assert.instanceOf(result[0],errors.NotActiveJwtParseError); }); }); @@ -226,7 +226,7 @@ describe('Verifier().verify() ',function(){ it('should return an unexpected algorithm error',function(){ assert.isNotNull(result[0],'An error was not returned'); - assert.equal(result[0].userMessage,properties.errors.SIGNATURE_ALGORITHM_MISMTACH); + assert.instanceOf(result[0],errors.SignatureAlgorithmMismatchJwtParseError); }); }); @@ -249,9 +249,9 @@ describe('Verifier().verify() ',function(){ }); }); - it('should return SIGNATURE_ALGORITHM_MISMTACH',function(){ + it('should return SignatureAlgorithmMismatchJwtParseError',function(){ assert.isNotNull(result[0],'An error was not returned'); - assert.equal(result[0].userMessage,properties.errors.SIGNATURE_ALGORITHM_MISMTACH); + assert.instanceOf(result[0],errors.SignatureAlgorithmMismatchJwtParseError); }); }); @@ -300,9 +300,9 @@ describe('Verifier().verify() ',function(){ }); }); - it('should return SIGNATURE_MISMTACH',function(){ + it('should return SignatureMismatchJwtParseError',function(){ assert.isNotNull(result[0],'An error was not returned'); - assert.equal(result[0].userMessage,properties.errors.SIGNATURE_MISMTACH); + assert.instanceOf(result[0],errors.SignatureMismatchJwtParseError); }); }); }); @@ -323,9 +323,9 @@ describe('Verifier().verify() ',function(){ }); }); - it('should return SIGNATURE_MISMTACH',function(){ + it('should return SignatureMismatchJwtParseError',function(){ assert.isNotNull(result[0], 'An error was not returned'); - assert.equal(result[0].userMessage,properties.errors.SIGNATURE_MISMTACH); + assert.instanceOf(result[0],errors.SignatureMismatchJwtParseError); }); }); });