Ghost/ghost/members-api/lib/services/token.js
Naz 9756094ae2 🐛 Fixed signing key mismatching in JWT/JWKS
refs https://github.com/TryGhost/Team/issues/1640
closes https://github.com/TryGhost/Members/pull/401/
refs https://forum.ghost.org/t/ghost-jwt-question-possible-bug/30210

- Without `keyid` parameter some of the clien libraries were not able to match the signin key to verify JWT
- Missing `keyid` parameter allows to indicate the key used to secure JWS (as per https://www.rfc-editor.org/rfc/rfc7515#section-4.1.4) and resolves the automatic matching issue on the client.
- The `kid` parameter was left in claims to avoid accidental breaking changes.
2022-05-23 18:45:08 +08:00

55 lines
1.3 KiB
JavaScript

const jose = require('node-jose');
const jwt = require('jsonwebtoken');
module.exports = class TokenService {
constructor({
privateKey,
publicKey,
issuer
}) {
this._keyStore = jose.JWK.createKeyStore();
this._keyStoreReady = this._keyStore.add(privateKey, 'pem');
this._privateKey = privateKey;
this._publicKey = publicKey;
this._issuer = issuer;
}
async encodeIdentityToken({sub}) {
const jwk = await this._keyStoreReady;
return jwt.sign({
sub,
kid: jwk.kid
}, this._privateKey, {
keyid: jwk.kid,
algorithm: 'RS512',
audience: this._issuer,
expiresIn: '10m',
issuer: this._issuer
});
}
/**
* @param {string} token
* @returns {Promise<jwt.JwtPayload>}
*/
async decodeToken(token) {
await this._keyStoreReady;
const result = jwt.verify(token, this._publicKey, {
algorithms: ['RS512'],
issuer: this._issuer
});
if (typeof result === 'string') {
return {sub: result};
}
return result;
}
async getPublicKeys() {
await this._keyStoreReady;
return this._keyStore.toJSON();
}
};