mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-22 16:29:09 +01:00
[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:
parent
ff3420d373
commit
cc0199d351
@ -237,6 +237,8 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
|
|||||||
request.email = this.authService.email;
|
request.email = this.authService.email;
|
||||||
request.masterPasswordHash = this.authService.masterPasswordHash;
|
request.masterPasswordHash = this.authService.masterPasswordHash;
|
||||||
request.deviceIdentifier = await this.appIdService.getAppId();
|
request.deviceIdentifier = await this.appIdService.getAppId();
|
||||||
|
request.authRequestAccessCode = this.authService.accessCode;
|
||||||
|
request.authRequestId = this.authService.authRequestId;
|
||||||
this.emailPromise = this.apiService.postTwoFactorEmail(request);
|
this.emailPromise = this.apiService.postTwoFactorEmail(request);
|
||||||
await this.emailPromise;
|
await this.emailPromise;
|
||||||
if (doToast) {
|
if (doToast) {
|
||||||
@ -274,7 +276,8 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
|
|||||||
return (
|
return (
|
||||||
this.authService.authingWithPassword() ||
|
this.authService.authingWithPassword() ||
|
||||||
this.authService.authingWithSso() ||
|
this.authService.authingWithSso() ||
|
||||||
this.authService.authingWithApiKey()
|
this.authService.authingWithApiKey() ||
|
||||||
|
this.authService.authingWithPasswordless()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,9 @@ import { AuthRequestPushNotification } from "../models/response/notification.res
|
|||||||
export abstract class AuthService {
|
export abstract class AuthService {
|
||||||
masterPasswordHash: string;
|
masterPasswordHash: string;
|
||||||
email: string;
|
email: string;
|
||||||
|
accessCode: string;
|
||||||
|
authRequestId: string;
|
||||||
|
|
||||||
logIn: (
|
logIn: (
|
||||||
credentials:
|
credentials:
|
||||||
| ApiLogInCredentials
|
| ApiLogInCredentials
|
||||||
@ -31,6 +34,7 @@ export abstract class AuthService {
|
|||||||
authingWithApiKey: () => boolean;
|
authingWithApiKey: () => boolean;
|
||||||
authingWithSso: () => boolean;
|
authingWithSso: () => boolean;
|
||||||
authingWithPassword: () => boolean;
|
authingWithPassword: () => boolean;
|
||||||
|
authingWithPasswordless: () => boolean;
|
||||||
getAuthStatus: (userId?: string) => Promise<AuthenticationStatus>;
|
getAuthStatus: (userId?: string) => Promise<AuthenticationStatus>;
|
||||||
authResponsePushNotifiction: (notification: AuthRequestPushNotification) => Promise<any>;
|
authResponsePushNotifiction: (notification: AuthRequestPushNotification) => Promise<any>;
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import { TokenService } from "../../abstractions/token.service";
|
|||||||
import { TwoFactorService } from "../../abstractions/twoFactor.service";
|
import { TwoFactorService } from "../../abstractions/twoFactor.service";
|
||||||
import { AuthResult } from "../../models/domain/auth-result";
|
import { AuthResult } from "../../models/domain/auth-result";
|
||||||
import { PasswordlessLogInCredentials } from "../../models/domain/log-in-credentials";
|
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 { PasswordTokenRequest } from "../../models/request/identity-token/password-token.request";
|
||||||
import { TokenTwoFactorRequest } from "../../models/request/identity-token/token-two-factor.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;
|
return this.tokenRequest.email;
|
||||||
}
|
}
|
||||||
|
|
||||||
get masterPasswordHash() {
|
get accessCode() {
|
||||||
return this.tokenRequest.masterPasswordHash;
|
return this.passwordlessCredentials.accessCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
get authRequestId() {
|
||||||
|
return this.passwordlessCredentials.authRequestId;
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenRequest: PasswordTokenRequest;
|
tokenRequest: PasswordTokenRequest;
|
||||||
|
private passwordlessCredentials: PasswordlessLogInCredentials;
|
||||||
private localHashedPassword: string;
|
|
||||||
private key: SymmetricCryptoKey;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
cryptoService: CryptoService,
|
cryptoService: CryptoService,
|
||||||
@ -56,8 +57,8 @@ export class PasswordlessLogInStrategy extends LogInStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onSuccessfulLogin() {
|
async onSuccessfulLogin() {
|
||||||
await this.cryptoService.setKey(this.key);
|
await this.cryptoService.setKey(this.passwordlessCredentials.decKey);
|
||||||
await this.cryptoService.setKeyHash(this.localHashedPassword);
|
await this.cryptoService.setKeyHash(this.passwordlessCredentials.localPasswordHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
async logInTwoFactor(
|
async logInTwoFactor(
|
||||||
@ -69,8 +70,7 @@ export class PasswordlessLogInStrategy extends LogInStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async logIn(credentials: PasswordlessLogInCredentials) {
|
async logIn(credentials: PasswordlessLogInCredentials) {
|
||||||
this.localHashedPassword = credentials.localPasswordHash;
|
this.passwordlessCredentials = credentials;
|
||||||
this.key = credentials.decKey;
|
|
||||||
|
|
||||||
this.tokenRequest = new PasswordTokenRequest(
|
this.tokenRequest = new PasswordTokenRequest(
|
||||||
credentials.email,
|
credentials.email,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
export class SecretVerificationRequest {
|
export class SecretVerificationRequest {
|
||||||
masterPasswordHash: string;
|
masterPasswordHash: string;
|
||||||
otp: string;
|
otp: string;
|
||||||
|
authRequestAccessCode: string;
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,5 @@ import { SecretVerificationRequest } from "./secret-verification.request";
|
|||||||
export class TwoFactorEmailRequest extends SecretVerificationRequest {
|
export class TwoFactorEmailRequest extends SecretVerificationRequest {
|
||||||
email: string;
|
email: string;
|
||||||
deviceIdentifier: string;
|
deviceIdentifier: string;
|
||||||
|
authRequestId: string;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,14 @@ const sessionTimeoutLength = 2 * 60 * 1000; // 2 minutes
|
|||||||
|
|
||||||
export class AuthService implements AuthServiceAbstraction {
|
export class AuthService implements AuthServiceAbstraction {
|
||||||
get email(): string {
|
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 {
|
get masterPasswordHash(): string {
|
||||||
@ -47,6 +54,18 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
: null;
|
: 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:
|
private logInStrategy:
|
||||||
| ApiLogInStrategy
|
| ApiLogInStrategy
|
||||||
| PasswordLogInStrategy
|
| PasswordLogInStrategy
|
||||||
@ -196,6 +215,10 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
return this.logInStrategy instanceof PasswordLogInStrategy;
|
return this.logInStrategy instanceof PasswordLogInStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
authingWithPasswordless(): boolean {
|
||||||
|
return this.logInStrategy instanceof PasswordlessLogInStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
async getAuthStatus(userId?: string): Promise<AuthenticationStatus> {
|
async getAuthStatus(userId?: string): Promise<AuthenticationStatus> {
|
||||||
const isAuthenticated = await this.stateService.getIsAuthenticated({ userId: userId });
|
const isAuthenticated = await this.stateService.getIsAuthenticated({ userId: userId });
|
||||||
if (!isAuthenticated) {
|
if (!isAuthenticated) {
|
||||||
|
Loading…
Reference in New Issue
Block a user