@bitblit/ratchet-epsilon-common
Version:
Tiny adapter to simplify building API gateway Lambda APIS
71 lines • 2.82 kB
JavaScript
import { Logger } from '@bitblit/ratchet-common/logger/logger';
import jwt from 'jsonwebtoken';
import jwks from 'jwks-rsa';
import fetch from 'cross-fetch';
import { StringRatchet } from '@bitblit/ratchet-common/lang/string-ratchet';
export class GoogleWebTokenManipulator {
clientId;
static GOOGLE_DISCOVERY_DOCUMENT = 'https://accounts.google.com/.well-known/openid-configuration';
cacheGoogleDiscoveryDocument;
jwksClient;
constructor(clientId) {
this.clientId = clientId;
}
async extractTokenFromAuthorizationHeader(authHeader) {
let tokenString = StringRatchet.trimToEmpty(authHeader);
if (tokenString.toLowerCase().startsWith('bearer ')) {
tokenString = tokenString.substring(7);
}
const validated = tokenString ? await this.parseAndValidateGoogleToken(tokenString, false) : null;
return validated;
}
async parseAndValidateGoogleToken(googleToken, allowExpired = false) {
Logger.debug('Auth : %s', StringRatchet.obscure(googleToken, 4));
const fullToken = jwt.decode(googleToken, { complete: true });
const kid = fullToken.header.kid;
const nowEpochSeconds = Math.floor(new Date().getTime() / 1000);
const pubKey = await this.fetchSigningKey(kid);
const validated = jwt.verify(googleToken, pubKey, {
audience: this.clientId,
issuer: ['https://accounts.google.com', 'accounts.google.com'],
ignoreExpiration: allowExpired,
clockTimestamp: nowEpochSeconds,
});
return validated;
}
async fetchSigningKey(kid) {
const jClient = await this.fetchJwksClient();
return new Promise((res, rej) => {
jClient.getSigningKey(kid, (err, key) => {
if (err) {
rej(err);
}
else {
res(key.publicKey || key.rsaPublicKey);
}
});
});
}
async fetchJwksClient() {
if (!this.jwksClient) {
const discDoc = await this.fetchGoogleDiscoveryDocument();
const client = jwks({
cache: true,
cacheMaxEntries: 5,
cacheMaxAge: 1000 * 60 * 60 * 10,
jwksUri: discDoc.jwks_uri,
});
this.jwksClient = client;
}
return this.jwksClient;
}
async fetchGoogleDiscoveryDocument() {
if (!this.cacheGoogleDiscoveryDocument) {
const resp = await fetch(GoogleWebTokenManipulator.GOOGLE_DISCOVERY_DOCUMENT);
const doc = await resp.json();
this.cacheGoogleDiscoveryDocument = doc;
}
return this.cacheGoogleDiscoveryDocument;
}
}
//# sourceMappingURL=google-web-token-manipulator.js.map