62 lines
2.3 KiB
TypeScript
62 lines
2.3 KiB
TypeScript
import { IdpGlobalServerClient } from './classes.idp-global-server-client.js';
|
|
import { SmartdataAccountStore } from './classes.account-store.js';
|
|
import type { IAuthenticateAccountOptions, IAuthenticatedAccountResult, IIdpSdkAccount } from './interfaces.js';
|
|
|
|
export class AccountAuthService {
|
|
constructor(private optionsArg: {
|
|
store: SmartdataAccountStore;
|
|
idpClient?: IdpGlobalServerClient;
|
|
}) {}
|
|
|
|
public async authenticate(optionsArg: IAuthenticateAccountOptions): Promise<IAuthenticatedAccountResult | null> {
|
|
const account = await this.optionsArg.store.getAccountByEmail(optionsArg.email);
|
|
if (!account || account.status !== 'active') {
|
|
return null;
|
|
}
|
|
|
|
const authSource = optionsArg.authSource || 'auto';
|
|
if ((authSource === 'local' || authSource === 'auto') && account.authSources.includes('local')) {
|
|
const localOk = await this.optionsArg.store.verifyLocalPassword(account, optionsArg.password);
|
|
if (localOk) {
|
|
const updatedAccount = await this.optionsArg.store.updateLoginState(account.id, {});
|
|
return { account: updatedAccount || account, authSource: 'local' };
|
|
}
|
|
if (authSource === 'local') {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
if ((authSource === 'idp.global' || authSource === 'auto') && account.authSources.includes('idp.global')) {
|
|
return this.authenticateWithIdp(account, optionsArg.password);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private async authenticateWithIdp(accountArg: IIdpSdkAccount, passwordArg: string): Promise<IAuthenticatedAccountResult | null> {
|
|
if (!this.optionsArg.idpClient) {
|
|
return null;
|
|
}
|
|
const idpResult = await this.optionsArg.idpClient.loginWithEmailAndPassword({
|
|
email: accountArg.email,
|
|
password: passwordArg,
|
|
});
|
|
const idpEmail = this.optionsArg.store.normalizeEmail(idpResult.user.data.email);
|
|
if (idpEmail !== accountArg.emailNormalized) {
|
|
return null;
|
|
}
|
|
if (accountArg.idpSubject && accountArg.idpSubject !== idpResult.user.id) {
|
|
return null;
|
|
}
|
|
const updatedAccount = await this.optionsArg.store.updateLoginState(accountArg.id, {
|
|
idpSubject: accountArg.idpSubject || idpResult.user.id,
|
|
});
|
|
return {
|
|
account: updatedAccount || accountArg,
|
|
authSource: 'idp.global',
|
|
idpJwt: idpResult.jwt,
|
|
idpRefreshToken: idpResult.refreshToken,
|
|
};
|
|
}
|
|
}
|