From a208a6c9571e571d1e693b3f031b86bf22a975a1 Mon Sep 17 00:00:00 2001 From: Fabien O'Carroll Date: Thu, 17 Sep 2020 15:59:02 +0100 Subject: [PATCH] Added JWTTokenProvider to preserve functionality no-issue This allows the magic-link module to be used with the current functionality with minimal changes --- ghost/magic-link/JWTTokenProvider.js | 50 ++++++++++++++++++++++++++++ ghost/magic-link/test/index.test.js | 5 +-- 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 ghost/magic-link/JWTTokenProvider.js diff --git a/ghost/magic-link/JWTTokenProvider.js b/ghost/magic-link/JWTTokenProvider.js new file mode 100644 index 0000000000..ef79b3e739 --- /dev/null +++ b/ghost/magic-link/JWTTokenProvider.js @@ -0,0 +1,50 @@ +const jwt = require('jsonwebtoken'); + +/** + * @typedef {import('jsonwebtoken').Secret} Secret + * @typedef {string} JSONWebToken + */ + +/** + * @typedef {Object} Data + */ + +module.exports = class JWTTokenProvider { + /** + * @param {Secret} secret + */ + constructor(secret) { + this.secret = secret; + } + + /** + * @param {Data} data + * @returns {Promise} + */ + async create(data) { + const token = jwt.sign(data, this.secret, { + algorithm: 'HS256', + expiresIn: '10m' + }); + + return token; + } + + /** + * @param {JSONWebToken} token + * @returns {Promise} + */ + async validate(token) { + /** @type any */ + const claims = jwt.verify(token, this.secret, { + algorithms: ['HS256'], + maxAge: '10m' + }); + + if (!claims || typeof claims === 'string') { + throw new Error(); + } + + return claims; + } +}; diff --git a/ghost/magic-link/test/index.test.js b/ghost/magic-link/test/index.test.js index eba3f36fa1..7416337593 100644 --- a/ghost/magic-link/test/index.test.js +++ b/ghost/magic-link/test/index.test.js @@ -1,6 +1,7 @@ const should = require('should'); const sinon = require('sinon'); const MagicLink = require('../'); +const JWTTokenProvider = require('../JWTTokenProvider'); const crypto = require('crypto'); const sandbox = sinon.createSandbox(); @@ -14,7 +15,7 @@ describe('MagicLink', function () { describe('#sendMagicLink', function () { it('Sends an email to the user with a link generated from getSigninURL(token, type)', async function () { const options = { - secret, + tokenProvider: new JWTTokenProvider(secret), getSigninURL: sandbox.stub().returns('FAKEURL'), getText: sandbox.stub().returns('SOMETEXT'), getHTML: sandbox.stub().returns('SOMEHTML'), @@ -57,7 +58,7 @@ describe('MagicLink', function () { describe('#getDataFromToken', function () { it('Returns the user data which from the token that was encoded by #sendMagicLink', async function () { const options = { - secret, + tokenProvider: new JWTTokenProvider(secret), getSigninURL: sandbox.stub().returns('FAKEURL'), getText: sandbox.stub().returns('SOMETEXT'), getHTML: sandbox.stub().returns('SOMEHTML'),