From bd527f597da70458bf863a8b3fe2ab8db2e80c5d Mon Sep 17 00:00:00 2001 From: Dustin Popp Date: Tue, 27 Dec 2022 12:20:29 -0500 Subject: [PATCH] fix(auth): migrate to secure usage of jwt for token authentication There is a vulnerability in v8 of the `jsonwebtoken` dependency. This commit upgrades to v9 to resolve the vulnerability. Additionally, they made an effort in this version to discourage the less secure "decode" method in favor of the more secure "verify" method (1). This commit also refactors the code and tests to use the "verify" method. (1) See this PR for context: https://github.com/auth0/node-jsonwebtoken/pull/741 Signed-off-by: Dustin Popp --- auth/token-managers/jwt-token-manager.ts | 19 +++- package-lock.json | 137 +++++++---------------- package.json | 2 +- test/unit/iam-token-manager.test.js | 2 +- test/unit/jwt-token-manager.test.js | 40 +++---- 5 files changed, 78 insertions(+), 122 deletions(-) diff --git a/auth/token-managers/jwt-token-manager.ts b/auth/token-managers/jwt-token-manager.ts index 5c5adcfd1..7f2aeba2b 100644 --- a/auth/token-managers/jwt-token-manager.ts +++ b/auth/token-managers/jwt-token-manager.ts @@ -16,7 +16,7 @@ * limitations under the License. */ -import { decode } from 'jsonwebtoken'; +import { verify } from 'jsonwebtoken'; import logger from '../../lib/logger'; import { TokenManager, TokenManagerOptions } from './token-manager'; @@ -80,15 +80,26 @@ export class JwtTokenManager extends TokenManager { throw new Error(err); } - // the time of expiration is found by decoding the JWT access token - // exp is the time of expire and iat is the time of token retrieval - const decodedResponse = decode(this.accessToken); + let decodedResponse; + try { + decodedResponse = verify(this.accessToken); + } catch (e) { + // the token is either an invalid JWT or it could not be verified + logger.error('Failed to verify the JWT. See error message:'); + logger.error(e); + throw new Error(e); + } + + // the 'catch' method above should handle any verificiation/decoding issues but + // this check is here as a failsafe if (!decodedResponse) { const err = 'Access token recieved is not a valid JWT'; logger.error(err); throw new Error(err); } + // the time of expiration is found by decoding the JWT access token + // 'exp' is the time of expire and 'iat' is the time of token retrieval const { exp, iat } = decodedResponse; // There are no required claims in JWT if (!exp || !iat) { diff --git a/package-lock.json b/package-lock.json index 83f50c136..0b5f4c0d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "file-type": "16.5.4", "form-data": "^2.3.3", "isstream": "~0.1.2", - "jsonwebtoken": "^8.5.1", + "jsonwebtoken": "^9.0.0", "lodash.isempty": "^4.4.0", "mime-types": "~2.1.18", "object.omit": "~3.0.0", @@ -8404,32 +8404,32 @@ } }, "node_modules/jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", + "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", "dependencies": { "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", + "lodash": "^4.17.21", "ms": "^2.1.1", - "semver": "^5.6.0" + "semver": "^7.3.8" }, "engines": { - "node": ">=4", - "npm": ">=1.4.28" + "node": ">=12", + "npm": ">=6" } }, "node_modules/jsonwebtoken/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { - "semver": "bin/semver" + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/jsx-ast-utils": { @@ -8592,8 +8592,7 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash.capitalize": { "version": "4.2.1", @@ -8613,16 +8612,6 @@ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" - }, "node_modules/lodash.isempty": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", @@ -8634,31 +8623,23 @@ "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", "dev": true }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" - }, "node_modules/lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", "dev": true }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" - }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true }, "node_modules/lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -8666,11 +8647,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -8706,7 +8682,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -14353,8 +14328,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { "version": "1.10.2", @@ -20839,26 +20813,23 @@ } }, "jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", + "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", "requires": { "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", + "lodash": "^4.17.21", "ms": "^2.1.1", - "semver": "^5.6.0" + "semver": "^7.3.8" }, "dependencies": { "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "requires": { + "lru-cache": "^6.0.0" + } } } }, @@ -20994,8 +20965,7 @@ "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash.capitalize": { "version": "4.2.1", @@ -21015,16 +20985,6 @@ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" - }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" - }, "lodash.isempty": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", @@ -21036,31 +20996,23 @@ "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", "dev": true }, - "lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" - }, "lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", "dev": true }, - "lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" - }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true }, "lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true }, "lodash.merge": { "version": "4.6.2", @@ -21068,11 +21020,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, "lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -21105,7 +21052,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -25182,8 +25128,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yaml": { "version": "1.10.2", diff --git a/package.json b/package.json index 3c969c6bd..185349aa4 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "file-type": "16.5.4", "form-data": "^2.3.3", "isstream": "~0.1.2", - "jsonwebtoken": "^8.5.1", + "jsonwebtoken": "^9.0.0", "lodash.isempty": "^4.4.0", "mime-types": "~2.1.18", "object.omit": "~3.0.0", diff --git a/test/unit/iam-token-manager.test.js b/test/unit/iam-token-manager.test.js index 1cf05ec29..a2dd270d5 100644 --- a/test/unit/iam-token-manager.test.js +++ b/test/unit/iam-token-manager.test.js @@ -21,7 +21,7 @@ const jwt = require('jsonwebtoken'); jest.mock('../../dist/lib/request-wrapper'); const { RequestWrapper } = require('../../dist/lib/request-wrapper'); -jwt.decode = jest.fn(() => ({ exp: 100, iat: 100 })); +jwt.verify = jest.fn(() => ({ exp: 100, iat: 100 })); const { IamTokenManager } = require('../../dist/auth'); diff --git a/test/unit/jwt-token-manager.test.js b/test/unit/jwt-token-manager.test.js index 7570031a6..377e050a4 100644 --- a/test/unit/jwt-token-manager.test.js +++ b/test/unit/jwt-token-manager.test.js @@ -47,8 +47,8 @@ describe('JWT Token Manager', () => { const instance = new JwtTokenManager(); const saveTokenInfoSpy = jest.spyOn(instance, 'saveTokenInfo'); - const decodeSpy = jest - .spyOn(jwt, 'decode') + const verifySpy = jest + .spyOn(jwt, 'verify') .mockImplementation((token) => ({ iat: 10, exp: 100 })); const requestTokenSpy = jest @@ -58,19 +58,19 @@ describe('JWT Token Manager', () => { const token = await instance.getToken(); expect(requestTokenSpy).toHaveBeenCalled(); expect(saveTokenInfoSpy).toHaveBeenCalled(); - expect(decodeSpy).toHaveBeenCalled(); + expect(verifySpy).toHaveBeenCalled(); expect(token).toBe(ACCESS_TOKEN); saveTokenInfoSpy.mockRestore(); - decodeSpy.mockRestore(); + verifySpy.mockRestore(); requestTokenSpy.mockRestore(); }); it('should pace token requests', async () => { const instance = new JwtTokenManager(); - const decodeSpy = jest - .spyOn(jwt, 'decode') + const verifySpy = jest + .spyOn(jwt, 'verify') .mockImplementation((token) => ({ iat: 10, exp: 100 })); const requestTokenSpy = jest.spyOn(instance, 'requestToken').mockImplementation( @@ -91,7 +91,7 @@ describe('JWT Token Manager', () => { expect(requestTokenSpy).toHaveBeenCalled(); expect(requestTokenSpy.mock.calls).toHaveLength(1); - decodeSpy.mockRestore(); + verifySpy.mockRestore(); requestTokenSpy.mockRestore(); }); @@ -131,8 +131,8 @@ describe('JWT Token Manager', () => { instance.tokenInfo.access_token = CURRENT_ACCESS_TOKEN; const saveTokenInfoSpy = jest.spyOn(instance, 'saveTokenInfo'); - const decodeSpy = jest - .spyOn(jwt, 'decode') + const verifySpy = jest + .spyOn(jwt, 'verify') .mockImplementation((token) => ({ iat: 10, exp: 100 })); const requestTokenSpy = jest @@ -142,11 +142,11 @@ describe('JWT Token Manager', () => { const token = await instance.getToken(); expect(requestTokenSpy).toHaveBeenCalled(); expect(saveTokenInfoSpy).toHaveBeenCalled(); - expect(decodeSpy).toHaveBeenCalled(); + expect(verifySpy).toHaveBeenCalled(); expect(token).toBe(CURRENT_ACCESS_TOKEN); saveTokenInfoSpy.mockRestore(); - decodeSpy.mockRestore(); + verifySpy.mockRestore(); requestTokenSpy.mockRestore(); }); @@ -271,8 +271,8 @@ describe('JWT Token Manager', () => { describe('saveTokenInfo', () => { it('should save information to object state', () => { const instance = new JwtTokenManager(); - const decodeSpy = jest - .spyOn(jwt, 'decode') + const verifySpy = jest + .spyOn(jwt, 'verify') .mockImplementation((token) => ({ iat: 10, exp: 100 })); const tokenResponse = { result: { access_token: ACCESS_TOKEN } }; @@ -280,7 +280,7 @@ describe('JWT Token Manager', () => { instance.saveTokenInfo(tokenResponse); expect(instance.expireTime).toBe(100); expect(instance.tokenInfo).toEqual(tokenResponse.result); - decodeSpy.mockRestore(); + verifySpy.mockRestore(); }); it('should throw an error when access token is undefined', () => { @@ -294,15 +294,15 @@ describe('JWT Token Manager', () => { describe('calculateTimeForNewToken', () => { it('should calculate time for new token based on valid jwt', () => { const instance = new JwtTokenManager(); - const decodeSpy = jest - .spyOn(jwt, 'decode') + const verifySpy = jest + .spyOn(jwt, 'verify') .mockImplementation((token) => ({ iat: 100, exp: 200 })); const tokenResponse = { result: { access_token: ACCESS_TOKEN } }; instance.saveTokenInfo(tokenResponse); expect(instance.refreshTime).toBe(180); - decodeSpy.mockRestore(); + verifySpy.mockRestore(); }); it('should throw an error if token is not a valid jwt', () => { @@ -312,8 +312,8 @@ describe('JWT Token Manager', () => { it('should gracefully handle a jwt without exp or iat claims', () => { const instance = new JwtTokenManager(); - const decodeSpy = jest - .spyOn(jwt, 'decode') + const verifySpy = jest + .spyOn(jwt, 'verify') .mockImplementation((token) => ({ foo: 0, bar: 100 })); const tokenResponse = { result: { access_token: ACCESS_TOKEN } }; @@ -321,7 +321,7 @@ describe('JWT Token Manager', () => { instance.saveTokenInfo(tokenResponse); expect(instance.expireTime).toBe(0); expect(instance.tokenInfo).toEqual(tokenResponse.result); - decodeSpy.mockRestore(); + verifySpy.mockRestore(); }); }); });