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.

194 lines
6.3 KiB

  1. var jwt = require('../index');
  2. var jws = require('jws');
  3. var fs = require('fs');
  4. var path = require('path');
  5. var sinon = require('sinon');
  6. var assert = require('chai').assert;
  7. describe('verify', function() {
  8. var pub = fs.readFileSync(path.join(__dirname, 'pub.pem'));
  9. var priv = fs.readFileSync(path.join(__dirname, 'priv.pem'));
  10. it('should first assume JSON claim set', function (done) {
  11. var header = { alg: 'RS256' };
  12. var payload = { iat: Math.floor(Date.now() / 1000 ) };
  13. var signed = jws.sign({
  14. header: header,
  15. payload: payload,
  16. secret: priv,
  17. encoding: 'utf8'
  18. });
  19. jwt.verify(signed, pub, {typ: 'JWT'}, function(err, p) {
  20. assert.isNull(err);
  21. assert.deepEqual(p, payload);
  22. done();
  23. });
  24. });
  25. it('should be able to validate unsigned token', function (done) {
  26. var header = { alg: 'none' };
  27. var payload = { iat: Math.floor(Date.now() / 1000 ) };
  28. var signed = jws.sign({
  29. header: header,
  30. payload: payload,
  31. secret: priv,
  32. encoding: 'utf8'
  33. });
  34. jwt.verify(signed, null, {typ: 'JWT'}, function(err, p) {
  35. assert.isNull(err);
  36. assert.deepEqual(p, payload);
  37. done();
  38. });
  39. });
  40. it('should not mutate options', function (done) {
  41. var header = { alg: 'none' };
  42. var payload = { iat: Math.floor(Date.now() / 1000 ) };
  43. var options = {typ: 'JWT'};
  44. var signed = jws.sign({
  45. header: header,
  46. payload: payload,
  47. secret: priv,
  48. encoding: 'utf8'
  49. });
  50. jwt.verify(signed, null, options, function(err) {
  51. assert.isNull(err);
  52. assert.deepEqual(Object.keys(options).length, 1);
  53. done();
  54. });
  55. });
  56. describe('expiration', function () {
  57. // { foo: 'bar', iat: 1437018582, exp: 1437018583 }
  58. var token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE0MzcwMTg1ODIsImV4cCI6MTQzNzAxODU4M30.NmMv7sXjM1dW0eALNXud8LoXknZ0mH14GtnFclwJv0s';
  59. var key = 'key';
  60. var clock;
  61. afterEach(function () {
  62. try { clock.restore(); } catch (e) {}
  63. });
  64. it('should error on expired token', function (done) {
  65. clock = sinon.useFakeTimers(1437018650000);
  66. var options = {algorithms: ['HS256']};
  67. jwt.verify(token, key, options, function (err, p) {
  68. assert.equal(err.name, 'TokenExpiredError');
  69. assert.equal(err.message, 'jwt expired');
  70. assert.equal(err.expiredAt.constructor.name, 'Date');
  71. assert.equal(Number(err.expiredAt), 1437018583000);
  72. assert.isUndefined(p);
  73. done();
  74. });
  75. });
  76. it('should not error on expired token within clockTolerance interval', function (done) {
  77. clock = sinon.useFakeTimers(1437018584000);
  78. var options = {algorithms: ['HS256'], clockTolerance: 100}
  79. jwt.verify(token, key, options, function (err, p) {
  80. assert.isNull(err);
  81. assert.equal(p.foo, 'bar');
  82. done();
  83. });
  84. });
  85. it('should not error if within maxAge timespan', function (done) {
  86. clock = sinon.useFakeTimers(1437018582500);
  87. var options = {algorithms: ['HS256'], maxAge: '600ms'};
  88. jwt.verify(token, key, options, function (err, p) {
  89. assert.isNull(err);
  90. assert.equal(p.foo, 'bar');
  91. done();
  92. });
  93. });
  94. describe('option: maxAge', function () {
  95. it('should error for claims issued before a certain timespan', function (done) {
  96. clock = sinon.useFakeTimers(1437018582500);
  97. var options = {algorithms: ['HS256'], maxAge: '321ms'};
  98. jwt.verify(token, key, options, function (err, p) {
  99. assert.equal(err.name, 'TokenExpiredError');
  100. assert.equal(err.message, 'maxAge exceeded');
  101. assert.equal(err.expiredAt.constructor.name, 'Date');
  102. assert.equal(Number(err.expiredAt), 1437018582321);
  103. assert.isUndefined(p);
  104. done();
  105. });
  106. });
  107. it('should not error for claims issued before a certain timespan but still inside clockTolerance timespan', function (done) {
  108. clock = sinon.useFakeTimers(1437018582500);
  109. var options = {algorithms: ['HS256'], maxAge: '321ms', clockTolerance: 100};
  110. jwt.verify(token, key, options, function (err, p) {
  111. assert.isNull(err);
  112. assert.equal(p.foo, 'bar');
  113. done();
  114. });
  115. });
  116. it('should not error if within maxAge timespan', function (done) {
  117. clock = sinon.useFakeTimers(1437018582500);
  118. var options = {algorithms: ['HS256'], maxAge: '600ms'};
  119. jwt.verify(token, key, options, function (err, p) {
  120. assert.isNull(err);
  121. assert.equal(p.foo, 'bar');
  122. done();
  123. });
  124. });
  125. it('can be more restrictive than expiration', function (done) {
  126. clock = sinon.useFakeTimers(1437018582900);
  127. var options = {algorithms: ['HS256'], maxAge: '800ms'};
  128. jwt.verify(token, key, options, function (err, p) {
  129. assert.equal(err.name, 'TokenExpiredError');
  130. assert.equal(err.message, 'maxAge exceeded');
  131. assert.equal(err.expiredAt.constructor.name, 'Date');
  132. assert.equal(Number(err.expiredAt), 1437018582800);
  133. assert.isUndefined(p);
  134. done();
  135. });
  136. });
  137. it('cannot be more permissive than expiration', function (done) {
  138. clock = sinon.useFakeTimers(1437018583100);
  139. var options = {algorithms: ['HS256'], maxAge: '1200ms'};
  140. jwt.verify(token, key, options, function (err, p) {
  141. // maxAge not exceded, but still expired
  142. assert.equal(err.name, 'TokenExpiredError');
  143. assert.equal(err.message, 'jwt expired');
  144. assert.equal(err.expiredAt.constructor.name, 'Date');
  145. assert.equal(Number(err.expiredAt), 1437018583000);
  146. assert.isUndefined(p);
  147. done();
  148. });
  149. });
  150. it('should error if maxAge is specified but there is no iat claim', function (done) {
  151. clock = sinon.useFakeTimers(1437018582900);
  152. var token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIifQ.0MBPd4Bru9-fK_HY3xmuDAc6N_embknmNuhdb9bKL_U';
  153. var options = {algorithms: ['HS256'], maxAge: '1s'};
  154. jwt.verify(token, key, options, function (err, p) {
  155. assert.equal(err.name, 'JsonWebTokenError');
  156. assert.equal(err.message, 'iat required when maxAge is specified');
  157. assert.isUndefined(p);
  158. done();
  159. });
  160. });
  161. });
  162. });
  163. });