75 lines
2.7 KiB
TypeScript
75 lines
2.7 KiB
TypeScript
|
|
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<plugins.typedsocket.TypedSocket>();
|
||
|
|
|
||
|
|
constructor(private optionsArg: IIdpGlobalServerClientOptions) {}
|
||
|
|
|
||
|
|
public async connect(): Promise<plugins.typedsocket.TypedSocket> {
|
||
|
|
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<void> {
|
||
|
|
await this.typedsocket?.stop();
|
||
|
|
this.typedsocket = undefined;
|
||
|
|
}
|
||
|
|
|
||
|
|
public async loginWithEmailAndPassword(optionsArg: { email: string; password: string }): Promise<IIdpPasswordAuthResult> {
|
||
|
|
const socket = await this.connect();
|
||
|
|
const loginRequest = socket.createTypedRequest<plugins.idpInterfaces.request.IReq_LoginWithEmailOrUsernameAndPassword>('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<plugins.idpInterfaces.request.IReq_RefreshJwt>('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<plugins.idpInterfaces.request.IReq_WhoIs>('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;
|
||
|
|
}
|
||
|
|
}
|