[SG-698] Passwordless Login with 2FA enabled does not redirect to 2FA page (#3820)

* added 2fa enabled

* added passwordless authentication to 2fa

* passwordless strategy to authservice

* changes to 2FA to allow email sending for passwordless

* updated imports
This commit is contained in:
Gbubemi Smith 2022-10-19 10:21:20 -06:00 committed by GitHub
parent ff3420d373
commit cc0199d351
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 44 additions and 12 deletions

View File

@ -237,6 +237,8 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
request.email = this.authService.email;
request.masterPasswordHash = this.authService.masterPasswordHash;
request.deviceIdentifier = await this.appIdService.getAppId();
request.authRequestAccessCode = this.authService.accessCode;
request.authRequestId = this.authService.authRequestId;
this.emailPromise = this.apiService.postTwoFactorEmail(request);
await this.emailPromise;
if (doToast) {
@ -274,7 +276,8 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
return (
this.authService.authingWithPassword() ||
this.authService.authingWithSso() ||
this.authService.authingWithApiKey()
this.authService.authingWithApiKey() ||
this.authService.authingWithPasswordless()
);
}

View File

@ -15,6 +15,9 @@ import { AuthRequestPushNotification } from "../models/response/notification.res
export abstract class AuthService {
masterPasswordHash: string;
email: string;
accessCode: string;
authRequestId: string;
logIn: (
credentials:
| ApiLogInCredentials
@ -31,6 +34,7 @@ export abstract class AuthService {
authingWithApiKey: () => boolean;
authingWithSso: () => boolean;
authingWithPassword: () => boolean;
authingWithPasswordless: () => boolean;
getAuthStatus: (userId?: string) => Promise<AuthenticationStatus>;
authResponsePushNotifiction: (notification: AuthRequestPushNotification) => Promise<any>;

View File

@ -10,7 +10,6 @@ import { TokenService } from "../../abstractions/token.service";
import { TwoFactorService } from "../../abstractions/twoFactor.service";
import { AuthResult } from "../../models/domain/auth-result";
import { PasswordlessLogInCredentials } from "../../models/domain/log-in-credentials";
import { SymmetricCryptoKey } from "../../models/domain/symmetric-crypto-key";
import { PasswordTokenRequest } from "../../models/request/identity-token/password-token.request";
import { TokenTwoFactorRequest } from "../../models/request/identity-token/token-two-factor.request";
@ -21,14 +20,16 @@ export class PasswordlessLogInStrategy extends LogInStrategy {
return this.tokenRequest.email;
}
get masterPasswordHash() {
return this.tokenRequest.masterPasswordHash;
get accessCode() {
return this.passwordlessCredentials.accessCode;
}
get authRequestId() {
return this.passwordlessCredentials.authRequestId;
}
tokenRequest: PasswordTokenRequest;
private localHashedPassword: string;
private key: SymmetricCryptoKey;
private passwordlessCredentials: PasswordlessLogInCredentials;
constructor(
cryptoService: CryptoService,
@ -56,8 +57,8 @@ export class PasswordlessLogInStrategy extends LogInStrategy {
}
async onSuccessfulLogin() {
await this.cryptoService.setKey(this.key);
await this.cryptoService.setKeyHash(this.localHashedPassword);
await this.cryptoService.setKey(this.passwordlessCredentials.decKey);
await this.cryptoService.setKeyHash(this.passwordlessCredentials.localPasswordHash);
}
async logInTwoFactor(
@ -69,8 +70,7 @@ export class PasswordlessLogInStrategy extends LogInStrategy {
}
async logIn(credentials: PasswordlessLogInCredentials) {
this.localHashedPassword = credentials.localPasswordHash;
this.key = credentials.decKey;
this.passwordlessCredentials = credentials;
this.tokenRequest = new PasswordTokenRequest(
credentials.email,

View File

@ -1,4 +1,5 @@
export class SecretVerificationRequest {
masterPasswordHash: string;
otp: string;
authRequestAccessCode: string;
}

View File

@ -3,4 +3,5 @@ import { SecretVerificationRequest } from "./secret-verification.request";
export class TwoFactorEmailRequest extends SecretVerificationRequest {
email: string;
deviceIdentifier: string;
authRequestId: string;
}

View File

@ -38,7 +38,14 @@ const sessionTimeoutLength = 2 * 60 * 1000; // 2 minutes
export class AuthService implements AuthServiceAbstraction {
get email(): string {
return this.logInStrategy instanceof PasswordLogInStrategy ? this.logInStrategy.email : null;
if (
this.logInStrategy instanceof PasswordLogInStrategy ||
this.logInStrategy instanceof PasswordlessLogInStrategy
) {
return this.logInStrategy.email;
}
return null;
}
get masterPasswordHash(): string {
@ -47,6 +54,18 @@ export class AuthService implements AuthServiceAbstraction {
: null;
}
get accessCode(): string {
return this.logInStrategy instanceof PasswordlessLogInStrategy
? this.logInStrategy.accessCode
: null;
}
get authRequestId(): string {
return this.logInStrategy instanceof PasswordlessLogInStrategy
? this.logInStrategy.authRequestId
: null;
}
private logInStrategy:
| ApiLogInStrategy
| PasswordLogInStrategy
@ -196,6 +215,10 @@ export class AuthService implements AuthServiceAbstraction {
return this.logInStrategy instanceof PasswordLogInStrategy;
}
authingWithPasswordless(): boolean {
return this.logInStrategy instanceof PasswordlessLogInStrategy;
}
async getAuthStatus(userId?: string): Promise<AuthenticationStatus> {
const isAuthenticated = await this.stateService.getIsAuthenticated({ userId: userId });
if (!isAuthenticated) {