diff --git a/test/ecdsa-private.pem b/test/ecdsa-private.pem new file mode 100644 index 0000000..aad4c4d --- /dev/null +++ b/test/ecdsa-private.pem @@ -0,0 +1,18 @@ +-----BEGIN EC PARAMETERS----- +MIH3AgEBMCwGByqGSM49AQECIQD/////AAAAAQAAAAAAAAAAAAAAAP////////// +/////zBbBCD/////AAAAAQAAAAAAAAAAAAAAAP///////////////AQgWsY12Ko6 +k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsDFQDEnTYIhucEk2pmeOETnSa3gZ9+ +kARBBGsX0fLhLEJH+Lzm5WOkQPJ3A32BLeszoPShOUXYmMKWT+NC4v4af5uO5+tK +fA+eFivOM1drMV7Oy7ZAaDe/UfUCIQD/////AAAAAP//////////vOb6racXnoTz +ucrC/GMlUQIBAQ== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIIBaAIBAQQgeg2m9tJJsnURyjTUihohiJahj9ETy3csUIt4EYrV+J2ggfowgfcC +AQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAAAAAAAAAAAAAA//////////////// +MFsEIP////8AAAABAAAAAAAAAAAAAAAA///////////////8BCBaxjXYqjqT57Pr +vVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSdNgiG5wSTamZ44ROdJreBn36QBEEE +axfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54W +K84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8 +YyVRAgEBoUQDQgAEEWluurrkZECnq27UpNauq16f9+5DDMFJZ3HV43Ujc3tcXQ++ +N1T/0CAA8ve286f32s7rkqX/pPokI/HBpP5p3g== +-----END EC PRIVATE KEY----- diff --git a/test/ecdsa-public-invalid.pem b/test/ecdsa-public-invalid.pem new file mode 100644 index 0000000..016d86d --- /dev/null +++ b/test/ecdsa-public-invalid.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBSzCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAA +AAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA//// +///////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSd +NgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5 +RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA +//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABEfZiYJDbghTGQ+KGnHGSl6K +yUqK/BL2uJIg7Z0bx48v6+L7Ve8MCS17eptkMT2e4l5B/ZGDVUHb6uZ5xFROLBw= +-----END PUBLIC KEY----- diff --git a/test/ecdsa-public-x509.pem b/test/ecdsa-public-x509.pem new file mode 100644 index 0000000..ef9fe22 --- /dev/null +++ b/test/ecdsa-public-x509.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDGjCCAsKgAwIBAgIJANuPNBWwp6wzMAkGByqGSM49BAEwRTELMAkGA1UEBhMC +QVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdp +dHMgUHR5IEx0ZDAeFw0xNzA2MTAxMTAzMjJaFw0yNzA2MDgxMTAzMjJaMEUxCzAJ +BgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5l +dCBXaWRnaXRzIFB0eSBMdGQwggFLMIIBAwYHKoZIzj0CATCB9wIBATAsBgcqhkjO +PQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAA +AAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQaw +zFOw9jvOPD4n0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEQQRrF9Hy4SxCR/i8 +5uVjpEDydwN9gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2 +QGg3v1H1AiEA/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQEDQgAE +EWluurrkZECnq27UpNauq16f9+5DDMFJZ3HV43Ujc3tcXQ++N1T/0CAA8ve286f3 +2s7rkqX/pPokI/HBpP5p3qOBpzCBpDAdBgNVHQ4EFgQUAF43lnAvCztZZGaGMoxs +cp6tpz8wdQYDVR0jBG4wbIAUAF43lnAvCztZZGaGMoxscp6tpz+hSaRHMEUxCzAJ +BgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5l +dCBXaWRnaXRzIFB0eSBMdGSCCQDbjzQVsKesMzAMBgNVHRMEBTADAQH/MAkGByqG +SM49BAEDRwAwRAIgV039oh2RtcSwywQ/0dWAwc20NHxrgmKoQ5A3AS5A9d0CIBCV +2AlKDFjmDC7zjldNhWbMcIlSSj71ghhhxeS0F8v1 +-----END CERTIFICATE----- diff --git a/test/ecdsa-public.pem b/test/ecdsa-public.pem new file mode 100644 index 0000000..6cfee2f --- /dev/null +++ b/test/ecdsa-public.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBSzCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAA +AAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA//// +///////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSd +NgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5 +RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA +//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABBFpbrq65GRAp6tu1KTWrqte +n/fuQwzBSWdx1eN1I3N7XF0PvjdU/9AgAPL3tvOn99rO65Kl/6T6JCPxwaT+ad4= +-----END PUBLIC KEY----- diff --git a/test/jwt.asymmetric_signing.tests.js b/test/jwt.asymmetric_signing.tests.js new file mode 100644 index 0000000..6f67aaf --- /dev/null +++ b/test/jwt.asymmetric_signing.tests.js @@ -0,0 +1,449 @@ +var jwt = require('../index'); +var fs = require('fs'); +var path = require('path'); + +var expect = require('chai').expect; +var assert = require('chai').assert; +var ms = require('ms'); + +function loadKey(filename) { + return fs.readFileSync(path.join(__dirname, filename)); +} + +var algorithms = { + RS256: { + pub_key: loadKey('pub.pem'), + priv_key: loadKey('priv.pem'), + invalid_pub_key: loadKey('invalid_pub.pem') + }, + ES256: { + // openssl ecparam -name secp256r1 -genkey -param_enc explicit -out ecdsa-private.pem + priv_key: loadKey('ecdsa-private.pem'), + // openssl ec -in ecdsa-private.pem -pubout -out ecdsa-public.pem + pub_key: loadKey('ecdsa-public.pem'), + invalid_pub_key: loadKey('ecdsa-public-invalid.pem') + } +}; + +describe('Asymmetric Algorithms', function(){ + + Object.keys(algorithms).forEach(function (algorithm) { + describe(algorithm, function () { + var pub = algorithms[algorithm].pub_key; + var priv = algorithms[algorithm].priv_key; + + // "invalid" means it is not the public key for the loaded "priv" key + var invalid_pub = algorithms[algorithm].invalid_pub_key; + + describe('when signing a token', function () { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm }); + + it('should be syntactically valid', function () { + expect(token).to.be.a('string'); + expect(token.split('.')).to.have.length(3); + }); + + context('asynchronous', function () { + it('should validate with public key', function (done) { + jwt.verify(token, pub, function (err, decoded) { + assert.ok(decoded.foo); + assert.equal('bar', decoded.foo); + done(); + }); + }); + + it('should throw with invalid public key', function (done) { + jwt.verify(token, invalid_pub, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + done(); + }); + }); + }); + + context('synchronous', function () { + it('should validate with public key', function () { + var decoded = jwt.verify(token, pub); + assert.ok(decoded.foo); + assert.equal('bar', decoded.foo); + }); + + it('should throw with invalid public key', function () { + var jwtVerify = jwt.verify.bind(null, token, invalid_pub) + assert.throw(jwtVerify, 'invalid signature'); + }); + }); + + }); + + describe('when signing a token with expiration', function () { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm, expiresIn: '10m' }); + + it('should be valid expiration', function (done) { + jwt.verify(token, pub, function (err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should be invalid', function (done) { + // expired token + token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm, expiresIn: -1 * ms('10m') }); + + jwt.verify(token, pub, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'TokenExpiredError'); + assert.instanceOf(err.expiredAt, Date); + assert.instanceOf(err, jwt.TokenExpiredError); + done(); + }); + }); + + it('should NOT be invalid', function (done) { + // expired token + token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm, expiresIn: -1 * ms('10m') }); + + jwt.verify(token, pub, { ignoreExpiration: true }, function (err, decoded) { + assert.ok(decoded.foo); + assert.equal('bar', decoded.foo); + done(); + }); + }); + }); + + describe('when signing a token with not before', function () { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm, notBefore: -10 * 3600 }); + + it('should be valid expiration', function (done) { + jwt.verify(token, pub, function (err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should be invalid', function (done) { + // not active token + token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm, notBefore: '10m' }); + + jwt.verify(token, pub, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'NotBeforeError'); + assert.instanceOf(err.date, Date); + assert.instanceOf(err, jwt.NotBeforeError); + done(); + }); + }); + + + it('should valid when date are equals', function (done) { + Date.fix(1451908031); + + token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm, notBefore: 0 }); + + jwt.verify(token, pub, function (err, decoded) { + assert.isNull(err); + assert.isNotNull(decoded); + Date.unfix(); + done(); + }); + }); + + it('should NOT be invalid', function (done) { + // not active token + token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm, notBefore: '10m' }); + + jwt.verify(token, pub, { ignoreNotBefore: true }, function (err, decoded) { + assert.ok(decoded.foo); + assert.equal('bar', decoded.foo); + done(); + }); + }); + }); + + describe('when signing a token with audience', function () { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm, audience: 'urn:foo' }); + + it('should check audience', function (done) { + jwt.verify(token, pub, { audience: 'urn:foo' }, function (err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should check audience in array', function (done) { + jwt.verify(token, pub, { audience: ['urn:foo', 'urn:other'] }, function (err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should throw when invalid audience', function (done) { + jwt.verify(token, pub, { audience: 'urn:wrong' }, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + + it('should throw when invalid audience in array', function (done) { + jwt.verify(token, pub, { audience: ['urn:wrong', 'urn:morewrong'] }, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + + }); + + describe('when signing a token with array audience', function () { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm, audience: ['urn:foo', 'urn:bar'] }); + + it('should check audience', function (done) { + jwt.verify(token, pub, { audience: 'urn:foo' }, function (err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should check other audience', function (done) { + jwt.verify(token, pub, { audience: 'urn:bar' }, function (err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should check audience in array', function (done) { + jwt.verify(token, pub, { audience: ['urn:foo', 'urn:other'] }, function (err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should throw when invalid audience', function (done) { + jwt.verify(token, pub, { audience: 'urn:wrong' }, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + + it('should throw when invalid audience in array', function (done) { + jwt.verify(token, pub, { audience: ['urn:wrong', 'urn:morewrong'] }, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + + }); + + describe('when signing a token without audience', function () { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm }); + + it('should check audience', function (done) { + jwt.verify(token, pub, { audience: 'urn:wrong' }, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + + it('should check audience in array', function (done) { + jwt.verify(token, pub, { audience: ['urn:wrong', 'urn:morewrong'] }, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + + }); + + describe('when signing a token with issuer', function () { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm, issuer: 'urn:foo' }); + + it('should check issuer', function (done) { + jwt.verify(token, pub, { issuer: 'urn:foo' }, function (err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should check the issuer when providing a list of valid issuers', function (done) { + jwt.verify(token, pub, { issuer: ['urn:foo', 'urn:bar'] }, function (err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should throw when invalid issuer', function (done) { + jwt.verify(token, pub, { issuer: 'urn:wrong' }, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + }); + + describe('when signing a token without issuer', function () { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm }); + + it('should check issuer', function (done) { + jwt.verify(token, pub, { issuer: 'urn:foo' }, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + }); + + describe('when signing a token with subject', function () { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm, subject: 'subject' }); + + it('should check subject', function (done) { + jwt.verify(token, pub, { subject: 'subject' }, function (err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should throw when invalid subject', function (done) { + jwt.verify(token, pub, { subject: 'wrongSubject' }, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + }); + + describe('when signing a token without subject', function () { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm }); + + it('should check subject', function (done) { + jwt.verify(token, pub, { subject: 'subject' }, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + }); + + describe('when signing a token with jwt id', function () { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm, jwtid: 'jwtid' }); + + it('should check jwt id', function (done) { + jwt.verify(token, pub, { jwtid: 'jwtid' }, function (err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should throw when invalid jwt id', function (done) { + jwt.verify(token, pub, { jwtid: 'wrongJwtid' }, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + }); + + describe('when signing a token without jwt id', function () { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm }); + + it('should check jwt id', function (done) { + jwt.verify(token, pub, { jwtid: 'jwtid' }, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + }); + + describe('when verifying a malformed token', function () { + it('should throw', function (done) { + jwt.verify('fruit.fruit.fruit', pub, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + done(); + }); + }); + }); + + describe('when decoding a jwt token with additional parts', function () { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: algorithm }); + + it('should throw', function (done) { + jwt.verify(token + '.foo', pub, function (err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + done(); + }); + }); + }); + + describe('when decoding a invalid jwt token', function () { + it('should return null', function (done) { + var payload = jwt.decode('whatever.token'); + assert.isNull(payload); + done(); + }); + }); + + describe('when decoding a valid jwt token', function () { + it('should return the payload', function (done) { + var obj = { foo: 'bar' }; + var token = jwt.sign(obj, priv, { algorithm: algorithm }); + var payload = jwt.decode(token); + assert.equal(payload.foo, obj.foo); + done(); + }); + it('should return the header and payload and signature if complete option is set', function (done) { + var obj = { foo: 'bar' }; + var token = jwt.sign(obj, priv, { algorithm: algorithm }); + var decoded = jwt.decode(token, { complete: true }); + assert.equal(decoded.payload.foo, obj.foo); + assert.deepEqual(decoded.header, { typ: 'JWT', alg: algorithm }); + assert.ok(typeof decoded.signature == 'string'); + done(); + }); + }); + }); + }); +}); diff --git a/test/jwt.rs.tests.js b/test/jwt.rs.tests.js deleted file mode 100644 index 5bd328a..0000000 --- a/test/jwt.rs.tests.js +++ /dev/null @@ -1,423 +0,0 @@ -var jwt = require('../index'); -var fs = require('fs'); -var path = require('path'); - -var expect = require('chai').expect; -var assert = require('chai').assert; -var ms = require('ms'); - -describe('RS256', function() { - var pub = fs.readFileSync(path.join(__dirname, 'pub.pem')); - var priv = fs.readFileSync(path.join(__dirname, 'priv.pem')); - var invalid_pub = fs.readFileSync(path.join(__dirname, 'invalid_pub.pem')); - - describe('when signing a token', function() { - var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256' }); - - it('should be syntactically valid', function() { - expect(token).to.be.a('string'); - expect(token.split('.')).to.have.length(3); - }); - - context('asynchronous', function() { - it('should validate with public key', function(done) { - jwt.verify(token, pub, function(err, decoded) { - assert.ok(decoded.foo); - assert.equal('bar', decoded.foo); - done(); - }); - }); - - it('should throw with invalid public key', function(done) { - jwt.verify(token, invalid_pub, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - done(); - }); - }); - }); - - context('synchronous', function() { - it('should validate with public key', function() { - var decoded = jwt.verify(token, pub); - assert.ok(decoded.foo); - assert.equal('bar', decoded.foo); - }); - - it('should throw with invalid public key', function() { - var jwtVerify = jwt.verify.bind(null, token, invalid_pub) - assert.throw(jwtVerify, 'invalid signature'); - }); - }); - - }); - - describe('when signing a token with expiration', function() { - var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', expiresIn: '10m' }); - - it('should be valid expiration', function(done) { - jwt.verify(token, pub, function(err, decoded) { - assert.isNotNull(decoded); - assert.isNull(err); - done(); - }); - }); - - it('should be invalid', function(done) { - // expired token - token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', expiresIn: -1 * ms('10m') }); - - jwt.verify(token, pub, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - assert.equal(err.name, 'TokenExpiredError'); - assert.instanceOf(err.expiredAt, Date); - assert.instanceOf(err, jwt.TokenExpiredError); - done(); - }); - }); - - it('should NOT be invalid', function(done) { - // expired token - token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', expiresIn: -1 * ms('10m') }); - - jwt.verify(token, pub, { ignoreExpiration: true }, function(err, decoded) { - assert.ok(decoded.foo); - assert.equal('bar', decoded.foo); - done(); - }); - }); - }); - - describe('when signing a token with not before', function() { - var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', notBefore: -10 * 3600 }); - - it('should be valid expiration', function(done) { - jwt.verify(token, pub, function(err, decoded) { - assert.isNotNull(decoded); - assert.isNull(err); - done(); - }); - }); - - it('should be invalid', function(done) { - // not active token - token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', notBefore: '10m' }); - - jwt.verify(token, pub, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - assert.equal(err.name, 'NotBeforeError'); - assert.instanceOf(err.date, Date); - assert.instanceOf(err, jwt.NotBeforeError); - done(); - }); - }); - - - it('should valid when date are equals', function(done) { - Date.fix(1451908031); - - token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', notBefore: 0 }); - - jwt.verify(token, pub, function(err, decoded) { - assert.isNull(err); - assert.isNotNull(decoded); - Date.unfix(); - done(); - }); - }); - - it('should NOT be invalid', function(done) { - // not active token - token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', notBefore: '10m' }); - - jwt.verify(token, pub, { ignoreNotBefore: true }, function(err, decoded) { - assert.ok(decoded.foo); - assert.equal('bar', decoded.foo); - done(); - }); - }); - }); - - describe('when signing a token with audience', function() { - var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', audience: 'urn:foo' }); - - it('should check audience', function(done) { - jwt.verify(token, pub, { audience: 'urn:foo' }, function(err, decoded) { - assert.isNotNull(decoded); - assert.isNull(err); - done(); - }); - }); - - it('should check audience in array', function(done) { - jwt.verify(token, pub, { audience: ['urn:foo', 'urn:other'] }, function (err, decoded) { - assert.isNotNull(decoded); - assert.isNull(err); - done(); - }); - }); - - it('should throw when invalid audience', function(done) { - jwt.verify(token, pub, { audience: 'urn:wrong' }, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - assert.equal(err.name, 'JsonWebTokenError'); - assert.instanceOf(err, jwt.JsonWebTokenError); - done(); - }); - }); - - it('should throw when invalid audience in array', function(done) { - jwt.verify(token, pub, { audience: ['urn:wrong', 'urn:morewrong'] }, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - assert.equal(err.name, 'JsonWebTokenError'); - assert.instanceOf(err, jwt.JsonWebTokenError); - done(); - }); - }); - - }); - - describe('when signing a token with array audience', function() { - var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', audience: [ 'urn:foo', 'urn:bar' ] }); - - it('should check audience', function(done) { - jwt.verify(token, pub, { audience: 'urn:foo' }, function(err, decoded) { - assert.isNotNull(decoded); - assert.isNull(err); - done(); - }); - }); - - it('should check other audience', function(done) { - jwt.verify(token, pub, { audience: 'urn:bar' }, function(err, decoded) { - assert.isNotNull(decoded); - assert.isNull(err); - done(); - }); - }); - - it('should check audience in array', function(done) { - jwt.verify(token, pub, { audience: ['urn:foo', 'urn:other'] }, function (err, decoded) { - assert.isNotNull(decoded); - assert.isNull(err); - done(); - }); - }); - - it('should throw when invalid audience', function(done) { - jwt.verify(token, pub, { audience: 'urn:wrong' }, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - assert.equal(err.name, 'JsonWebTokenError'); - assert.instanceOf(err, jwt.JsonWebTokenError); - done(); - }); - }); - - it('should throw when invalid audience in array', function(done) { - jwt.verify(token, pub, { audience: ['urn:wrong', 'urn:morewrong'] }, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - assert.equal(err.name, 'JsonWebTokenError'); - assert.instanceOf(err, jwt.JsonWebTokenError); - done(); - }); - }); - - }); - - describe('when signing a token without audience', function() { - var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256' }); - - it('should check audience', function(done) { - jwt.verify(token, pub, { audience: 'urn:wrong' }, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - assert.equal(err.name, 'JsonWebTokenError'); - assert.instanceOf(err, jwt.JsonWebTokenError); - done(); - }); - }); - - it('should check audience in array', function(done) { - jwt.verify(token, pub, { audience: ['urn:wrong', 'urn:morewrong'] }, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - assert.equal(err.name, 'JsonWebTokenError'); - assert.instanceOf(err, jwt.JsonWebTokenError); - done(); - }); - }); - - }); - - describe('when signing a token with issuer', function() { - var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', issuer: 'urn:foo' }); - - it('should check issuer', function(done) { - jwt.verify(token, pub, { issuer: 'urn:foo' }, function(err, decoded) { - assert.isNotNull(decoded); - assert.isNull(err); - done(); - }); - }); - - it('should check the issuer when providing a list of valid issuers', function(done) { - jwt.verify(token, pub, { issuer: [ 'urn:foo', 'urn:bar' ] }, function(err, decoded) { - assert.isNotNull(decoded); - assert.isNull(err); - done(); - }); - }); - - it('should throw when invalid issuer', function(done) { - jwt.verify(token, pub, { issuer: 'urn:wrong' }, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - assert.equal(err.name, 'JsonWebTokenError'); - assert.instanceOf(err, jwt.JsonWebTokenError); - done(); - }); - }); - }); - - describe('when signing a token without issuer', function() { - var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256' }); - - it('should check issuer', function(done) { - jwt.verify(token, pub, { issuer: 'urn:foo' }, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - assert.equal(err.name, 'JsonWebTokenError'); - assert.instanceOf(err, jwt.JsonWebTokenError); - done(); - }); - }); - }); - - describe('when signing a token with subject', function() { - var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', subject: 'subject' }); - - it('should check subject', function(done) { - jwt.verify(token, pub, { subject: 'subject' }, function(err, decoded) { - assert.isNotNull(decoded); - assert.isNull(err); - done(); - }); - }); - - it('should throw when invalid subject', function(done) { - jwt.verify(token, pub, { subject: 'wrongSubject' }, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - assert.equal(err.name, 'JsonWebTokenError'); - assert.instanceOf(err, jwt.JsonWebTokenError); - done(); - }); - }); - }); - - describe('when signing a token without subject', function() { - var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256' }); - - it('should check subject', function(done) { - jwt.verify(token, pub, { subject: 'subject' }, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - assert.equal(err.name, 'JsonWebTokenError'); - assert.instanceOf(err, jwt.JsonWebTokenError); - done(); - }); - }); - }); - - describe('when signing a token with jwt id', function() { - var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', jwtid: 'jwtid' }); - - it('should check jwt id', function(done) { - jwt.verify(token, pub, { jwtid: 'jwtid' }, function(err, decoded) { - assert.isNotNull(decoded); - assert.isNull(err); - done(); - }); - }); - - it('should throw when invalid jwt id', function(done) { - jwt.verify(token, pub, { jwtid: 'wrongJwtid' }, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - assert.equal(err.name, 'JsonWebTokenError'); - assert.instanceOf(err, jwt.JsonWebTokenError); - done(); - }); - }); - }); - - describe('when signing a token without jwt id', function() { - var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256' }); - - it('should check jwt id', function(done) { - jwt.verify(token, pub, { jwtid: 'jwtid' }, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - assert.equal(err.name, 'JsonWebTokenError'); - assert.instanceOf(err, jwt.JsonWebTokenError); - done(); - }); - }); - }); - - describe('when verifying a malformed token', function() { - it('should throw', function(done) { - jwt.verify('fruit.fruit.fruit', pub, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - assert.equal(err.name, 'JsonWebTokenError'); - done(); - }); - }); - }); - - describe('when decoding a jwt token with additional parts', function() { - var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256' }); - - it('should throw', function(done) { - jwt.verify(token + '.foo', pub, function(err, decoded) { - assert.isUndefined(decoded); - assert.isNotNull(err); - done(); - }); - }); - }); - - describe('when decoding a invalid jwt token', function() { - it('should return null', function(done) { - var payload = jwt.decode('whatever.token'); - assert.isNull(payload); - done(); - }); - }); - - describe('when decoding a valid jwt token', function() { - it('should return the payload', function(done) { - var obj = { foo: 'bar' }; - var token = jwt.sign(obj, priv, { algorithm: 'RS256' }); - var payload = jwt.decode(token); - assert.equal(payload.foo, obj.foo); - done(); - }); - it('should return the header and payload and signature if complete option is set', function(done) { - var obj = { foo: 'bar' }; - var token = jwt.sign(obj, priv, { algorithm: 'RS256' }); - var decoded = jwt.decode(token, { complete: true }); - assert.equal(decoded.payload.foo, obj.foo); - assert.deepEqual(decoded.header, { typ: 'JWT', alg: 'RS256' }); - assert.ok(typeof decoded.signature == 'string'); - done(); - }); - }); -});