diff --git a/ghost/members-api/lib/MembersAPI.js b/ghost/members-api/lib/MembersAPI.js index a1ab9c9dd8..35487a35d1 100644 --- a/ghost/members-api/lib/MembersAPI.js +++ b/ghost/members-api/lib/MembersAPI.js @@ -58,6 +58,12 @@ module.exports = function MembersAPI({ common.logging.setLogger(logger); } + const tokenService = new TokenService({ + privateKey, + publicKey, + issuer + }); + const stripeConfig = paymentConfig && paymentConfig.stripe || {}; const stripeAPIService = new StripeAPIService({ @@ -90,6 +96,7 @@ module.exports = function MembersAPI({ const memberRepository = new MemberRepository({ stripeAPIService, logger, + tokenService, productRepository, Member, MemberSubscribeEvent, @@ -128,12 +135,6 @@ module.exports = function MembersAPI({ sendEmailWithMagicLink }); - const tokenService = new TokenService({ - privateKey, - publicKey, - issuer - }); - const geolocationService = new GeolocationSerice(); const magicLinkService = new MagicLink({ diff --git a/ghost/members-api/lib/repositories/member.js b/ghost/members-api/lib/repositories/member.js index 8ff0aacc87..b622fcc78f 100644 --- a/ghost/members-api/lib/repositories/member.js +++ b/ghost/members-api/lib/repositories/member.js @@ -12,6 +12,11 @@ const messages = { bulkActionRequiresFilter: 'Cannot perform {action} without a filter or all=true' }; +/** + * @typedef {object} ITokenService + * @prop {(token: string) => Promise} decodeToken + */ + module.exports = class MemberRepository { /** * @param {object} deps @@ -25,6 +30,7 @@ module.exports = class MemberRepository { * @param {any} deps.StripeCustomerSubscription * @param {any} deps.productRepository * @param {import('../../services/stripe-api')} deps.stripeAPIService + * @param {ITokenService} deps.tokenService * @param {any} deps.logger */ constructor({ @@ -38,6 +44,7 @@ module.exports = class MemberRepository { StripeCustomerSubscription, stripeAPIService, productRepository, + tokenService, logger }) { this._Member = Member; @@ -50,6 +57,7 @@ module.exports = class MemberRepository { this._StripeCustomerSubscription = StripeCustomerSubscription; this._stripeAPIService = stripeAPIService; this._productRepository = productRepository; + this.tokenService = tokenService; this._logging = logger; } @@ -76,6 +84,14 @@ module.exports = class MemberRepository { return this._Member.findOne(data, options); } + async getByToken(token, options) { + const data = await this.tokenService.decodeToken(token); + + return this.get({ + email: data.sub + }, options); + } + async create(data, options) { const {labels} = data; diff --git a/ghost/members-api/lib/services/token.js b/ghost/members-api/lib/services/token.js index 5c0223c4ec..29c4de4063 100644 --- a/ghost/members-api/lib/services/token.js +++ b/ghost/members-api/lib/services/token.js @@ -29,14 +29,21 @@ module.exports = class TokenService { /** * @param {string} token + * @returns {Promise} */ async decodeToken(token) { await this._keyStoreReady; - return jwt.verify(token, this._publicKey, { + const result = jwt.verify(token, this._publicKey, { algorithms: ['RS512'], issuer: this._issuer }); + + if (typeof result === 'string') { + return {sub: result}; + } + + return result; } async getPublicKeys() {