import jwksClient from 'jwks-rsa'; import * as jsonwebtoken from 'jsonwebtoken'; import JwksRsa = require('jwks-rsa'); import {AppLogger} from '../../../logger'; import {DecodedToken} from '../../dto'; import {AuthenticationGuardModuleConfig} from '../authentication.guard.module'; import {Injectable} from '@nestjs/common'; @Injectable() export class AuthenticationGuardService { private readonly TAG: string = `${this.constructor.name}`; protected serviceAccountEmailRgx: string = `@([^.]+).${this.config.hostDomain}$`; constructor(private readonly config: AuthenticationGuardModuleConfig) { AppLogger.log('Init', this.TAG); } public async verify(token: string, serviceAccountOnly: boolean): Promise { const client: JwksRsa.JwksClient = jwksClient({ jwksUri: this.config.jwksRoute, }); function getKey(header, callback) { client.getSigningKey(header.kid, (err, key) => { if (err) { AppLogger.error(err, 'AuthenticationGuard'); return callback(null, null); } const signingKey = key['publicKey'] || key['rsaPublicKey']; callback(null, signingKey); }); } return new Promise((resolve, reject) => { const serviceAccountEmailRegex: RegExp = RegExp(this.serviceAccountEmailRgx); jsonwebtoken.verify(token, getKey, {}, (err, decoded: DecodedToken) => { if (err) { AppLogger.error(err, this.TAG); reject(false); } else { if (serviceAccountOnly) { const isValidEmail: boolean = serviceAccountEmailRegex.test(decoded.email); if (isValidEmail) { AppLogger.log('Access token verified successfully for service-account account', this.TAG); resolve(decoded); return; } AppLogger.warn('Access token verified but rejected since it is not a service-account access token', this.TAG); reject(null); return; } AppLogger.log('Access token verified successfully for account-management', this.TAG); resolve(decoded); return; } }); }); } }