diff --git a/package-lock.json b/package-lock.json index 367d50d553..09fb4736c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,7 @@ "graphql-tag": "2.12.6", "intersect": "1.0.1", "ip-range-check": "0.2.0", - "jsonwebtoken": "8.5.1", + "jsonwebtoken": "9.0.0", "jwks-rsa": "2.1.5", "ldapjs": "2.3.3", "lodash": "4.17.21", @@ -2863,6 +2863,35 @@ } } }, + "node_modules/@parse/node-apn/node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "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", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, + "node_modules/@parse/node-apn/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/@parse/node-gcm": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@parse/node-gcm/-/node-gcm-1.0.2.tgz", @@ -10167,32 +10196,18 @@ } }, "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_modules/jsonwebtoken/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" + "node": ">=12", + "npm": ">=6" } }, "node_modules/jsprim": { @@ -22697,6 +22712,28 @@ "requires": { "ms": "2.1.2" } + }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "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", + "ms": "^2.1.1", + "semver": "^5.6.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, @@ -28397,27 +28434,14 @@ } }, "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" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } + "semver": "^7.3.8" } }, "jsprim": { diff --git a/package.json b/package.json index 2b162c0ee2..947a197bb5 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "graphql-tag": "2.12.6", "intersect": "1.0.1", "ip-range-check": "0.2.0", - "jsonwebtoken": "8.5.1", + "jsonwebtoken": "9.0.0", "jwks-rsa": "2.1.5", "ldapjs": "2.3.3", "lodash": "4.17.21", diff --git a/spec/AuthenticationAdapters.spec.js b/spec/AuthenticationAdapters.spec.js index a940880cbf..bb89596cef 100644 --- a/spec/AuthenticationAdapters.spec.js +++ b/spec/AuthenticationAdapters.spec.js @@ -648,6 +648,7 @@ describe('instagram auth adapter', () => { describe('google auth adapter', () => { const google = require('../lib/Adapters/Auth/google'); const jwt = require('jsonwebtoken'); + const authUtils = require('../lib/Adapters/Auth/utils'); it('should throw error with missing id_token', async () => { try { @@ -670,7 +671,7 @@ describe('google auth adapter', () => { // it('should throw error if public key used to encode token is not available', async () => { // const fakeDecodedToken = { header: { kid: '789', alg: 'RS256' } }; // try { - // spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + // spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); // await google.validateAuthData({ id: 'the_user_id', id_token: 'the_token' }, {}); // fail(); @@ -689,7 +690,7 @@ describe('google auth adapter', () => { sub: 'the_user_id', }; const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); spyOn(jwt, 'verify').and.callFake(() => fakeClaim); const result = await google.validateAuthData( @@ -705,7 +706,7 @@ describe('google auth adapter', () => { sub: 'the_user_id', }; const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); spyOn(jwt, 'verify').and.callFake(() => fakeClaim); try { @@ -729,7 +730,7 @@ describe('google auth adapter', () => { sub: 'the_user_id', }; const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); spyOn(jwt, 'verify').and.callFake(() => fakeClaim); try { @@ -751,7 +752,7 @@ describe('google auth adapter', () => { sub: 'the_user_id', }; const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); spyOn(jwt, 'verify').and.callFake(() => fakeClaim); try { @@ -1454,6 +1455,7 @@ describe('apple signin auth adapter', () => { const apple = require('../lib/Adapters/Auth/apple'); const jwt = require('jsonwebtoken'); const util = require('util'); + const authUtils = require('../lib/Adapters/Auth/utils'); it('(using client id as string) should throw error with missing id_token', async () => { try { @@ -1488,7 +1490,7 @@ describe('apple signin auth adapter', () => { it('should throw error if public key used to encode token is not available', async () => { const fakeDecodedToken = { header: { kid: '789', alg: 'RS256' } }; try { - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken.header); await apple.validateAuthData( { id: 'the_user_id', token: 'the_token' }, @@ -1510,7 +1512,7 @@ describe('apple signin auth adapter', () => { sub: 'the_user_id', }; const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken.header); spyOn(jwt, 'verify').and.callFake(() => fakeClaim); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', rsaPublicKey: 'the_rsa_public_key' }; @@ -1527,7 +1529,7 @@ describe('apple signin auth adapter', () => { it('should not verify invalid id_token', async () => { const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', rsaPublicKey: 'the_rsa_public_key' }; }; @@ -1564,7 +1566,7 @@ describe('apple signin auth adapter', () => { sub: 'the_user_id', }; const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', rsaPublicKey: 'the_rsa_public_key' }; }; @@ -1586,7 +1588,7 @@ describe('apple signin auth adapter', () => { sub: 'the_user_id', }; const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', rsaPublicKey: 'the_rsa_public_key' }; }; @@ -1608,7 +1610,7 @@ describe('apple signin auth adapter', () => { sub: 'the_user_id', }; const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', rsaPublicKey: 'the_rsa_public_key' }; }; @@ -1628,7 +1630,7 @@ describe('apple signin auth adapter', () => { sub: 'the_user_id', }; const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', rsaPublicKey: 'the_rsa_public_key' }; }; @@ -1656,7 +1658,7 @@ describe('apple signin auth adapter', () => { sub: 'the_user_id', }; const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', rsaPublicKey: 'the_rsa_public_key' }; }; @@ -1685,7 +1687,7 @@ describe('apple signin auth adapter', () => { sub: 'the_user_id', }; const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', rsaPublicKey: 'the_rsa_public_key' }; }; @@ -1757,7 +1759,7 @@ describe('apple signin auth adapter', () => { sub: 'a_different_user_id', }; const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', rsaPublicKey: 'the_rsa_public_key' }; }; @@ -2024,6 +2026,7 @@ describe('facebook limited auth adapter', () => { const facebook = require('../lib/Adapters/Auth/facebook'); const jwt = require('jsonwebtoken'); const util = require('util'); + const authUtils = require('../lib/Adapters/Auth/utils'); // TODO: figure out a way to run this test alongside facebook classic tests xit('(using client id as string) should throw error with missing id_token', async () => { @@ -2062,7 +2065,7 @@ describe('facebook limited auth adapter', () => { header: { kid: '789', alg: 'RS256' }, }; try { - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken.header); await facebook.validateAuthData( { id: 'the_user_id', token: 'the_token' }, @@ -2086,7 +2089,7 @@ describe('facebook limited auth adapter', () => { const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' }, }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken.header); spyOn(jwt, 'verify').and.callFake(() => fakeClaim); const fakeGetSigningKeyAsyncFunction = () => { return { @@ -2108,7 +2111,7 @@ describe('facebook limited auth adapter', () => { const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' }, }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', @@ -2150,7 +2153,7 @@ describe('facebook limited auth adapter', () => { const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' }, }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', @@ -2177,7 +2180,7 @@ describe('facebook limited auth adapter', () => { const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' }, }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', @@ -2204,7 +2207,7 @@ describe('facebook limited auth adapter', () => { const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' }, }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', @@ -2229,7 +2232,7 @@ describe('facebook limited auth adapter', () => { const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' }, }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', @@ -2262,7 +2265,7 @@ describe('facebook limited auth adapter', () => { const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' }, }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', @@ -2296,7 +2299,7 @@ describe('facebook limited auth adapter', () => { const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' }, }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', @@ -2382,7 +2385,7 @@ describe('facebook limited auth adapter', () => { const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' }, }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); const fakeGetSigningKeyAsyncFunction = () => { return { kid: '123', diff --git a/spec/index.spec.js b/spec/index.spec.js index 5747d525df..64c4b54db7 100644 --- a/spec/index.spec.js +++ b/spec/index.spec.js @@ -587,6 +587,7 @@ describe('server', () => { it('should not fail when Google signin is introduced without the optional clientId', done => { const jwt = require('jsonwebtoken'); + const authUtils = require('../lib/Adapters/Auth/utils'); reconfigureServer({ auth: { google: {} }, @@ -599,7 +600,7 @@ describe('server', () => { sub: 'the_user_id', }; const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } }; - spyOn(jwt, 'decode').and.callFake(() => fakeDecodedToken); + spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken); spyOn(jwt, 'verify').and.callFake(() => fakeClaim); const user = new Parse.User(); user diff --git a/src/Adapters/Auth/apple.js b/src/Adapters/Auth/apple.js index 18989a4529..15b28ed203 100644 --- a/src/Adapters/Auth/apple.js +++ b/src/Adapters/Auth/apple.js @@ -5,6 +5,7 @@ const Parse = require('parse/node').Parse; const jwksClient = require('jwks-rsa'); const util = require('util'); const jwt = require('jsonwebtoken'); +const authUtils = require('./utils'); const TOKEN_ISSUER = 'https://appleid.apple.com'; @@ -30,21 +31,12 @@ const getAppleKeyByKeyId = async (keyId, cacheMaxEntries, cacheMaxAge) => { return key; }; -const getHeaderFromToken = token => { - const decodedToken = jwt.decode(token, { complete: true }); - if (!decodedToken) { - throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, `provided token does not decode as JWT`); - } - - return decodedToken.header; -}; - const verifyIdToken = async ({ token, id }, { clientId, cacheMaxEntries, cacheMaxAge }) => { if (!token) { throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, `id token is invalid for this user.`); } - const { kid: keyId, alg: algorithm } = getHeaderFromToken(token); + const { kid: keyId, alg: algorithm } = authUtils.getHeaderFromToken(token); const ONE_HOUR_IN_MS = 3600000; let jwtClaims; diff --git a/src/Adapters/Auth/facebook.js b/src/Adapters/Auth/facebook.js index e937bb1bb5..737657c8bd 100644 --- a/src/Adapters/Auth/facebook.js +++ b/src/Adapters/Auth/facebook.js @@ -5,6 +5,7 @@ const jwksClient = require('jwks-rsa'); const util = require('util'); const jwt = require('jsonwebtoken'); const httpsRequest = require('./httpsRequest'); +const authUtils = require('./utils'); const TOKEN_ISSUER = 'https://facebook.com'; @@ -73,21 +74,12 @@ const getFacebookKeyByKeyId = async (keyId, cacheMaxEntries, cacheMaxAge) => { return key; }; -const getHeaderFromToken = token => { - const decodedToken = jwt.decode(token, { complete: true }); - if (!decodedToken) { - throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'provided token does not decode as JWT'); - } - - return decodedToken.header; -}; - const verifyIdToken = async ({ token, id }, { clientId, cacheMaxEntries, cacheMaxAge }) => { if (!token) { throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'id token is invalid for this user.'); } - const { kid: keyId, alg: algorithm } = getHeaderFromToken(token); + const { kid: keyId, alg: algorithm } = authUtils.getHeaderFromToken(token); const ONE_HOUR_IN_MS = 3600000; let jwtClaims; diff --git a/src/Adapters/Auth/google.js b/src/Adapters/Auth/google.js index 8691cf9cae..755eb3c673 100644 --- a/src/Adapters/Auth/google.js +++ b/src/Adapters/Auth/google.js @@ -5,6 +5,7 @@ var Parse = require('parse/node').Parse; const https = require('https'); const jwt = require('jsonwebtoken'); +const authUtils = require('./utils'); const TOKEN_ISSUER = 'accounts.google.com'; const HTTPS_TOKEN_ISSUER = 'https://accounts.google.com'; @@ -51,22 +52,12 @@ function getGoogleKeyByKeyId(keyId) { }); } -function getHeaderFromToken(token) { - const decodedToken = jwt.decode(token, { complete: true }); - - if (!decodedToken) { - throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, `provided token does not decode as JWT`); - } - - return decodedToken.header; -} - async function verifyIdToken({ id_token: token, id }, { clientId }) { if (!token) { throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, `id token is invalid for this user.`); } - const { kid: keyId, alg: algorithm } = getHeaderFromToken(token); + const { kid: keyId, alg: algorithm } = authUtils.getHeaderFromToken(token); let jwtClaims; const googleKey = await getGoogleKeyByKeyId(keyId); diff --git a/src/Adapters/Auth/utils.js b/src/Adapters/Auth/utils.js new file mode 100644 index 0000000000..c50adaba79 --- /dev/null +++ b/src/Adapters/Auth/utils.js @@ -0,0 +1,13 @@ +const jwt = require('jsonwebtoken'); +const Parse = require('parse/node').Parse; +const getHeaderFromToken = token => { + const decodedToken = jwt.decode(token, { complete: true }); + if (!decodedToken) { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, `provided token does not decode as JWT`); + } + + return decodedToken.header; +}; +module.exports = { + getHeaderFromToken, +};