import * as plugins from './plugins.js'; export interface IIdpGlobalServerClientOptions { baseUrl: string; } export interface IIdpPasswordAuthResult { user: plugins.idpInterfaces.data.IUser; jwt: string; refreshToken: string; } export class IdpGlobalServerClient { private typedrouter: any = new plugins.typedrequest.TypedRouter(); private typedsocket?: plugins.typedsocket.TypedSocket; private typedsocketDeferred = plugins.smartpromise.defer(); constructor(private optionsArg: IIdpGlobalServerClientOptions) {} public async connect(): Promise { if (this.typedsocketDeferred.claimed) { return this.typedsocketDeferred.promise; } this.typedsocketDeferred.claim(); this.typedsocket = await plugins.typedsocket.TypedSocket.createClient( this.typedrouter, this.getTypedRequestUrl(), ); this.typedsocketDeferred.resolve(this.typedsocket); return this.typedsocketDeferred.promise; } public async stop(): Promise { await this.typedsocket?.stop(); this.typedsocket = undefined; } public async loginWithEmailAndPassword(optionsArg: { email: string; password: string }): Promise { const socket = await this.connect(); const loginRequest = socket.createTypedRequest('loginWithEmailOrUsernameAndPassword'); const loginResponse = await loginRequest.fire({ username: optionsArg.email, password: optionsArg.password, }); if (!loginResponse.refreshToken || loginResponse.twoFaNeeded) { throw new Error(loginResponse.twoFaNeeded ? 'Two-factor authentication is required' : 'IdP login failed'); } const refreshRequest = socket.createTypedRequest('refreshJwt'); const refreshResponse = await refreshRequest.fire({ refreshToken: loginResponse.refreshToken }); if (!refreshResponse.jwt) { throw new Error('IdP did not return a JWT'); } const whoIsRequest = socket.createTypedRequest('whoIs'); const whoIsResponse = await whoIsRequest.fire({ jwt: refreshResponse.jwt }); return { user: whoIsResponse.user, jwt: refreshResponse.jwt, refreshToken: refreshResponse.refreshToken || loginResponse.refreshToken, }; } private getTypedRequestUrl(): string { let baseUrl = this.optionsArg.baseUrl.trim(); if (baseUrl.endsWith('/')) { baseUrl = baseUrl.slice(0, -1); } if (!baseUrl.endsWith('/typedrequest')) { baseUrl = `${baseUrl}/typedrequest`; } return baseUrl; } }