From d12b40fb96d56786a96c06a621f3d8e0a0d24f4a Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 7 Oct 2022 11:06:28 +0200 Subject: Implement two factor in client --- client/src/app/+login/login.component.ts | 38 +++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 6 deletions(-) (limited to 'client/src/app/+login/login.component.ts') diff --git a/client/src/app/+login/login.component.ts b/client/src/app/+login/login.component.ts index 2ed9be16c..9095e43a7 100644 --- a/client/src/app/+login/login.component.ts +++ b/client/src/app/+login/login.component.ts @@ -4,7 +4,8 @@ import { ActivatedRoute, Router } from '@angular/router' import { AuthService, Notifier, RedirectService, SessionStorageService, UserService } from '@app/core' import { HooksService } from '@app/core/plugins/hooks.service' import { LOGIN_PASSWORD_VALIDATOR, LOGIN_USERNAME_VALIDATOR } from '@app/shared/form-validators/login-validators' -import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' +import { USER_OTP_TOKEN_VALIDATOR } from '@app/shared/form-validators/user-validators' +import { FormReactive, FormValidatorService, InputTextComponent } from '@app/shared/shared-forms' import { InstanceAboutAccordionComponent } from '@app/shared/shared-instance' import { NgbAccordion, NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' import { PluginsManager } from '@root-helpers/plugins-manager' @@ -20,6 +21,7 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni private static SESSION_STORAGE_REDIRECT_URL_KEY = 'login-previous-url' @ViewChild('forgotPasswordModal', { static: true }) forgotPasswordModal: ElementRef + @ViewChild('otpTokenInput') otpTokenInput: InputTextComponent accordion: NgbAccordion error: string = null @@ -37,6 +39,8 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni codeOfConduct: false } + otpStep = false + private openedForgotPasswordModal: NgbModalRef private serverConfig: ServerConfig @@ -82,7 +86,11 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni // Avoid undefined errors when accessing form error properties this.buildForm({ username: LOGIN_USERNAME_VALIDATOR, - password: LOGIN_PASSWORD_VALIDATOR + password: LOGIN_PASSWORD_VALIDATOR, + 'otp-token': { + VALIDATORS: [], // Will be set dynamically + MESSAGES: USER_OTP_TOKEN_VALIDATOR.MESSAGES + } }) this.serverConfig = snapshot.data.serverConfig @@ -118,13 +126,20 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni login () { this.error = null - const { username, password } = this.form.value + const options = { + username: this.form.value['username'], + password: this.form.value['password'], + otpToken: this.form.value['otp-token'] + } - this.authService.login(username, password) + this.authService.login(options) + .pipe() .subscribe({ next: () => this.redirectService.redirectToPreviousRoute(), - error: err => this.handleError(err) + error: err => { + this.handleError(err) + } }) } @@ -162,7 +177,7 @@ The link will expire within 1 hour.` private loadExternalAuthToken (username: string, token: string) { this.isAuthenticatedWithExternalAuth = true - this.authService.login(username, null, token) + this.authService.login({ username, password: null, token }) .subscribe({ next: () => { const redirectUrl = this.storage.getItem(LoginComponent.SESSION_STORAGE_REDIRECT_URL_KEY) @@ -182,6 +197,17 @@ The link will expire within 1 hour.` } private handleError (err: any) { + if (this.authService.isOTPMissingError(err)) { + this.otpStep = true + + setTimeout(() => { + this.form.get('otp-token').setValidators(USER_OTP_TOKEN_VALIDATOR.VALIDATORS) + this.otpTokenInput.focus() + }) + + return + } + if (err.message.indexOf('credentials are invalid') !== -1) this.error = $localize`Incorrect username or password.` else if (err.message.indexOf('blocked') !== -1) this.error = $localize`Your account is blocked.` else this.error = err.message -- cgit v1.2.3