mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-06 09:20:43 +01:00
[AuthService refactor] Don't clear state if 2FA is invalid (#690)
* Don't clear state if 2FA is invalid * Add session timeout to 2FA * Clear internal authService state if unhandled error
This commit is contained in:
parent
fdaa4f9fa5
commit
1cbc119ad8
@ -119,6 +119,7 @@ import { ValidationService } from "./validation.service";
|
|||||||
EnvironmentServiceAbstraction,
|
EnvironmentServiceAbstraction,
|
||||||
StateServiceAbstraction,
|
StateServiceAbstraction,
|
||||||
TwoFactorServiceAbstraction,
|
TwoFactorServiceAbstraction,
|
||||||
|
I18nServiceAbstraction,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -3,6 +3,7 @@ import { AppIdService } from "../abstractions/appId.service";
|
|||||||
import { AuthService as AuthServiceAbstraction } from "../abstractions/auth.service";
|
import { AuthService as AuthServiceAbstraction } from "../abstractions/auth.service";
|
||||||
import { CryptoService } from "../abstractions/crypto.service";
|
import { CryptoService } from "../abstractions/crypto.service";
|
||||||
import { EnvironmentService } from "../abstractions/environment.service";
|
import { EnvironmentService } from "../abstractions/environment.service";
|
||||||
|
import { I18nService } from "../abstractions/i18n.service";
|
||||||
import { KeyConnectorService } from "../abstractions/keyConnector.service";
|
import { KeyConnectorService } from "../abstractions/keyConnector.service";
|
||||||
import { LogService } from "../abstractions/log.service";
|
import { LogService } from "../abstractions/log.service";
|
||||||
import { MessagingService } from "../abstractions/messaging.service";
|
import { MessagingService } from "../abstractions/messaging.service";
|
||||||
@ -24,6 +25,9 @@ import {
|
|||||||
import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey";
|
import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey";
|
||||||
import { TokenRequestTwoFactor } from "../models/request/identityToken/tokenRequest";
|
import { TokenRequestTwoFactor } from "../models/request/identityToken/tokenRequest";
|
||||||
import { PreloginRequest } from "../models/request/preloginRequest";
|
import { PreloginRequest } from "../models/request/preloginRequest";
|
||||||
|
import { ErrorResponse } from "../models/response/errorResponse";
|
||||||
|
|
||||||
|
const sessionTimeoutLength = 2 * 60 * 1000; // 2 minutes
|
||||||
|
|
||||||
export class AuthService implements AuthServiceAbstraction {
|
export class AuthService implements AuthServiceAbstraction {
|
||||||
get email(): string {
|
get email(): string {
|
||||||
@ -37,6 +41,7 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private logInStrategy: ApiLogInStrategy | PasswordLogInStrategy | SsoLogInStrategy;
|
private logInStrategy: ApiLogInStrategy | PasswordLogInStrategy | SsoLogInStrategy;
|
||||||
|
private sessionTimeout: any;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected cryptoService: CryptoService,
|
protected cryptoService: CryptoService,
|
||||||
@ -49,7 +54,8 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
protected keyConnectorService: KeyConnectorService,
|
protected keyConnectorService: KeyConnectorService,
|
||||||
protected environmentService: EnvironmentService,
|
protected environmentService: EnvironmentService,
|
||||||
protected stateService: StateService,
|
protected stateService: StateService,
|
||||||
protected twoFactorService: TwoFactorService
|
protected twoFactorService: TwoFactorService,
|
||||||
|
protected i18nService: I18nService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async logIn(
|
async logIn(
|
||||||
@ -110,10 +116,24 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async logInTwoFactor(twoFactor: TokenRequestTwoFactor): Promise<AuthResult> {
|
async logInTwoFactor(twoFactor: TokenRequestTwoFactor): Promise<AuthResult> {
|
||||||
|
if (this.logInStrategy == null) {
|
||||||
|
throw new Error(this.i18nService.t("sessionTimeout"));
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await this.logInStrategy.logInTwoFactor(twoFactor);
|
const result = await this.logInStrategy.logInTwoFactor(twoFactor);
|
||||||
} finally {
|
|
||||||
this.clearState();
|
// Only clear state if 2FA token has been accepted, otherwise we need to be able to try again
|
||||||
|
if (!result.requiresTwoFactor) {
|
||||||
|
this.clearState();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (e) {
|
||||||
|
// API exceptions are okay, but if there are any unhandled client-side errors then clear state to be safe
|
||||||
|
if (!(e instanceof ErrorResponse)) {
|
||||||
|
this.clearState();
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,9 +174,22 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
|
|
||||||
private saveState(strategy: ApiLogInStrategy | PasswordLogInStrategy | SsoLogInStrategy) {
|
private saveState(strategy: ApiLogInStrategy | PasswordLogInStrategy | SsoLogInStrategy) {
|
||||||
this.logInStrategy = strategy;
|
this.logInStrategy = strategy;
|
||||||
|
this.startSessionTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
private clearState() {
|
private clearState() {
|
||||||
this.logInStrategy = null;
|
this.logInStrategy = null;
|
||||||
|
this.clearSessionTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
private startSessionTimeout() {
|
||||||
|
this.clearSessionTimeout();
|
||||||
|
this.sessionTimeout = setTimeout(() => this.clearState(), sessionTimeoutLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
private clearSessionTimeout() {
|
||||||
|
if (this.sessionTimeout != null) {
|
||||||
|
clearTimeout(this.sessionTimeout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user