import {HttpService, Injectable, Logger} from '@nestjs/common'; import {Client, Issuer, TokenSet} from "openid-client"; import {ConfigService} from "@nestjs/config"; @Injectable() export class AuthService { private Client!: Client; private _tokenSet!: TokenSet; private logger: Logger = new Logger('AuthService'); constructor( private readonly http: HttpService, private readonly config: ConfigService ) { } async client() { if (!this.Client) { const issuer = await Issuer.discover(this.config.get('KC_ISSUER')); const {Client} = issuer; this.Client = new Client({ client_id: this.config.get('KC_CLIENT'), client_secret: this.config.get('KC_SECRET'), }); this.Client.authorizationUrl({scope: 'offline_access'}) } return this.Client; } get accessToken() { return this._tokenSet.access_token; } get refreshToken() { return this._tokenSet.refresh_token; } async login() { const Client = await this.client(); return Client.grant({ grant_type: 'client_credentials', }).then((c) => { this.logger.debug('Get access token'); this._tokenSet = c; return c; }).catch(error => { this.logger.error(`Error login ${error}`); }); } async refresh() { const Client = await this.client(); return Client.refresh(this._tokenSet.refresh_token).then((c) => { this.logger.debug('Refresh token'); this._tokenSet = c; return c; }).catch(error => { this.logger.error(`Error refreshing token ${error}`); return this.login(); }); } get isTokenExpired(): boolean { return this._tokenSet.expired(); } async isActive() { const Client = await this.client(); return Client.introspect(this.accessToken).then(({active}) => active); } async tokenLife() { const expiresIn = this._tokenSet.expires_in / 60; const lifeTime = Number(this.config.get('TOKEN_LIFETIME')); return Number((100 - (lifeTime - expiresIn) * 100 / lifeTime).toFixed(1)); } async logout() { const Client = await this.client(); return await Client.revoke(this._tokenSet.access_token); } }