UNPKG

@bitblit/ratchet-epsilon-common

Version:

Tiny adapter to simplify building API gateway Lambda APIS

71 lines 2.82 kB
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