You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					289 lines
				
				9.3 KiB
			
		
		
			
		
	
	
					289 lines
				
				9.3 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								var jwt = require('../index');
							 | 
						||
| 
								 | 
							
								var fs = require('fs');
							 | 
						||
| 
								 | 
							
								var path = require('path');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var expect = require('chai').expect;
							 | 
						||
| 
								 | 
							
								var assert = require('chai').assert;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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', expiresInMinutes: 10 });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    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', expiresInMinutes: -10 });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      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', expiresInMinutes: -10 });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      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 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() {
							 | 
						||
| 
								 | 
							
								      jwt.verify(token, pub, { issuer: 'urn:foo' }, function(err, decoded) {
							 | 
						||
| 
								 | 
							
								        assert.isNotNull(decoded);
							 | 
						||
| 
								 | 
							
								        assert.isNull(err);
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    it('should throw when invalid issuer', function() {
							 | 
						||
| 
								 | 
							
								      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);
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  describe('when signing a token without issuer', function() {
							 | 
						||
| 
								 | 
							
								    var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256' });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    it('should check issuer', function() {
							 | 
						||
| 
								 | 
							
								      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);
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  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.deepEqual(payload, obj);
							 | 
						||
| 
								 | 
							
								      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.deepEqual(decoded.payload, obj);
							 | 
						||
| 
								 | 
							
								      assert.deepEqual(decoded.header, { typ: 'JWT', alg: 'RS256' });
							 | 
						||
| 
								 | 
							
								      assert.ok(typeof decoded.signature == 'string');
							 | 
						||
| 
								 | 
							
								      done();
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								});
							 |