0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-10 23:36:14 -05:00

Added ability to fetch member by identity token (#329)

refs https://github.com/TryGhost/Team/issues/1057

This method will validate a token, and then return the member associated
with it. Rather than exposing token validation and coupling consumers to
the structure of the token response data.
This commit is contained in:
Fabien 'egg' O'Carroll 2021-09-17 11:25:57 +02:00 committed by GitHub
parent d99e0acf1a
commit 528fd23874
3 changed files with 31 additions and 7 deletions

View file

@ -58,6 +58,12 @@ module.exports = function MembersAPI({
common.logging.setLogger(logger); common.logging.setLogger(logger);
} }
const tokenService = new TokenService({
privateKey,
publicKey,
issuer
});
const stripeConfig = paymentConfig && paymentConfig.stripe || {}; const stripeConfig = paymentConfig && paymentConfig.stripe || {};
const stripeAPIService = new StripeAPIService({ const stripeAPIService = new StripeAPIService({
@ -90,6 +96,7 @@ module.exports = function MembersAPI({
const memberRepository = new MemberRepository({ const memberRepository = new MemberRepository({
stripeAPIService, stripeAPIService,
logger, logger,
tokenService,
productRepository, productRepository,
Member, Member,
MemberSubscribeEvent, MemberSubscribeEvent,
@ -128,12 +135,6 @@ module.exports = function MembersAPI({
sendEmailWithMagicLink sendEmailWithMagicLink
}); });
const tokenService = new TokenService({
privateKey,
publicKey,
issuer
});
const geolocationService = new GeolocationSerice(); const geolocationService = new GeolocationSerice();
const magicLinkService = new MagicLink({ const magicLinkService = new MagicLink({

View file

@ -12,6 +12,11 @@ const messages = {
bulkActionRequiresFilter: 'Cannot perform {action} without a filter or all=true' bulkActionRequiresFilter: 'Cannot perform {action} without a filter or all=true'
}; };
/**
* @typedef {object} ITokenService
* @prop {(token: string) => Promise<import('jsonwebtoken').JwtPayload>} decodeToken
*/
module.exports = class MemberRepository { module.exports = class MemberRepository {
/** /**
* @param {object} deps * @param {object} deps
@ -25,6 +30,7 @@ module.exports = class MemberRepository {
* @param {any} deps.StripeCustomerSubscription * @param {any} deps.StripeCustomerSubscription
* @param {any} deps.productRepository * @param {any} deps.productRepository
* @param {import('../../services/stripe-api')} deps.stripeAPIService * @param {import('../../services/stripe-api')} deps.stripeAPIService
* @param {ITokenService} deps.tokenService
* @param {any} deps.logger * @param {any} deps.logger
*/ */
constructor({ constructor({
@ -38,6 +44,7 @@ module.exports = class MemberRepository {
StripeCustomerSubscription, StripeCustomerSubscription,
stripeAPIService, stripeAPIService,
productRepository, productRepository,
tokenService,
logger logger
}) { }) {
this._Member = Member; this._Member = Member;
@ -50,6 +57,7 @@ module.exports = class MemberRepository {
this._StripeCustomerSubscription = StripeCustomerSubscription; this._StripeCustomerSubscription = StripeCustomerSubscription;
this._stripeAPIService = stripeAPIService; this._stripeAPIService = stripeAPIService;
this._productRepository = productRepository; this._productRepository = productRepository;
this.tokenService = tokenService;
this._logging = logger; this._logging = logger;
} }
@ -76,6 +84,14 @@ module.exports = class MemberRepository {
return this._Member.findOne(data, options); 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) { async create(data, options) {
const {labels} = data; const {labels} = data;

View file

@ -29,14 +29,21 @@ module.exports = class TokenService {
/** /**
* @param {string} token * @param {string} token
* @returns {Promise<jwt.JwtPayload>}
*/ */
async decodeToken(token) { async decodeToken(token) {
await this._keyStoreReady; await this._keyStoreReady;
return jwt.verify(token, this._publicKey, { const result = jwt.verify(token, this._publicKey, {
algorithms: ['RS512'], algorithms: ['RS512'],
issuer: this._issuer issuer: this._issuer
}); });
if (typeof result === 'string') {
return {sub: result};
}
return result;
} }
async getPublicKeys() { async getPublicKeys() {