import {Injectable, Logger} from '@nestjs/common'; import {Client, Issuer, TokenSet} from "openid-client"; import {ConfigService} from "@nestjs/config"; import {Store} from "../store"; @Injectable() export class AuthService { private Client!: Client; private _tokenSet!: TokenSet; private logger: Logger = new Logger('AuthService'); constructor( private readonly config: ConfigService, private readonly _store: Store, ) { } get store() { return this._store; } 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; } async login() { const Client = await this.client(); return Client.grant({ grant_type: 'client_credentials', scope: 'offline_access', }).then((c) => { this.logger.debug('Get access token'); this.store.setToken(c); return c; }).catch(error => { this.logger.error(`Error login ${error}`); }); } async refresh() { const Client = await this.client(); return Client.refresh(this.store.token.refresh_token).then((c) => { this.logger.debug('Refresh token'); this.store.setToken(c); return c; }).catch(error => { this.logger.error(`Error refreshing token ${error}`); return this.login(); }); } get isTokenExpired(): boolean { return this.store.token.expired(); } async isActive() { const Client = await this.client(); return Client.introspect(this.store.accessToken).then(({active}) => active); } async tokenLife() { const expiresIn = this.store.token.expires_in / 60; const lifeTime = Number(this.config.get('TOKEN_LIFETIME')); console.log('expiresIn', expiresIn, 'lifeTime', lifeTime); return Number((100 - (lifeTime - expiresIn) * 100 / lifeTime).toFixed(1)); } async logout() { const Client = await this.client(); return await Client.revoke(this.store.accessToken); } }