mirror of
https://github.com/SuiteCRM/SuiteCRM-Core.git
synced 2025-08-29 21:00:39 +08:00
Add Two Factor Authentication Popup
This commit is contained in:
parent
e99d51b4e7
commit
f96cb90da8
9 changed files with 496 additions and 32 deletions
|
@ -725,3 +725,6 @@ export * from './views/2fa/components/2fa/2fa.component';
|
|||
export * from './views/2fa/components/2fa/2fa.module';
|
||||
export * from './views/2fa/components/2fa-check/2fa-check.component';
|
||||
export * from './views/2fa/components/2fa-check/2fa-check.module';
|
||||
export * from './views/2fa/components/2fa-check-modal/2fa-check-modal.component';
|
||||
export * from './views/2fa/components/2fa-check-modal/2fa-check-modal.module';
|
||||
export * from './views/2fa/components/2fa-check-modal/2fa-check-modal.model';
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2024 SalesAgility Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
|
||||
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License
|
||||
* version 3, these Appropriate Legal Notices must retain the display of the
|
||||
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
|
||||
* feasible for technical reasons, the Appropriate Legal Notices must display
|
||||
* the words "Supercharged by SuiteCRM".
|
||||
*/
|
||||
|
||||
import {Injectable} from '@angular/core';
|
||||
import {take} from 'rxjs/operators';
|
||||
import {Process, ProcessService} from "../../process.service";
|
||||
import {Observable} from "rxjs";
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class CheckTwoFactorCode {
|
||||
|
||||
|
||||
constructor(
|
||||
protected processService: ProcessService,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Auth Code
|
||||
*/
|
||||
public checkCode(auth_code): Observable<Process> {
|
||||
|
||||
const processType = 'check-two-factor-code';
|
||||
|
||||
const options = {
|
||||
auth_code
|
||||
};
|
||||
|
||||
return this.processService.submit(processType, options).pipe(take(1));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
<! --
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2024 SalesAgility Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
|
||||
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License
|
||||
* version 3, these Appropriate Legal Notices must retain the display of the
|
||||
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
|
||||
* feasible for technical reasons, the Appropriate Legal Notices must display
|
||||
* the words "Supercharged by SuiteCRM".
|
||||
*/
|
||||
-->
|
||||
<scrm-modal [closable]="false"
|
||||
bodyKlass="m-0 small-font"
|
||||
footerKlass="border-0"
|
||||
headerKlass="border-0"
|
||||
klass="two-factor-popup">
|
||||
|
||||
<div modal-body>
|
||||
<div>
|
||||
<div class="d-flex flex-column pt-4 align-items-center">
|
||||
<scrm-label labelKey="LBL_ENTER_AUTH_APP_2FA_CODE" class="pb-4"></scrm-label>
|
||||
<input [(ngModel)]="authCode"
|
||||
id="auth_code"
|
||||
type="text"
|
||||
name="auth_code"
|
||||
autocomplete="off"
|
||||
class="mb-3 auth-input"
|
||||
maxlength="6"/>
|
||||
|
||||
<button id="submit-2fa-code"
|
||||
(click)="checkCode()"
|
||||
type="submit"
|
||||
class="btn btn-sm btn-main mb-1">
|
||||
<scrm-label labelKey="LBL_VERIFY_2FA"></scrm-label>
|
||||
</button>
|
||||
|
||||
<div class="small mt-2 text-muted">
|
||||
<scrm-label labelKey="LBL_PROBLEMS_GENERATING_CODE"></scrm-label>
|
||||
</div>
|
||||
<div class="small mb-2 text-muted">
|
||||
<scrm-label labelKey="LBL_BACKUP_CODES_FALLBACK_INSTRUCTIONS"></scrm-label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</scrm-modal>
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2024 SalesAgility Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
|
||||
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License
|
||||
* version 3, these Appropriate Legal Notices must retain the display of the
|
||||
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
|
||||
* feasible for technical reasons, the Appropriate Legal Notices must display
|
||||
* the words "Supercharged by SuiteCRM".
|
||||
*/
|
||||
import {Component, HostListener} from "@angular/core";
|
||||
import {NgbActiveModal} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {LanguageStore} from "../../../../store/language/language.store";
|
||||
import {CheckTwoFactorCode} from "../../../../services/process/processes/check-two-factor-code/check-two-factor-code";
|
||||
import {TwoFactorCheckModalResult} from "./2fa-check-modal.model";
|
||||
import {MessageService} from "../../../../services/message/message.service";
|
||||
|
||||
@Component({
|
||||
selector: 'scrm-2fa-modal',
|
||||
templateUrl: './2fa-check-modal.component.html',
|
||||
styleUrls: [],
|
||||
})
|
||||
export class TwoFactorCheckModalComponent {
|
||||
|
||||
authCode: string;
|
||||
|
||||
|
||||
@HostListener('keyup.control.enter')
|
||||
onEnterKey() {
|
||||
this.checkCode();
|
||||
}
|
||||
|
||||
constructor(
|
||||
public activeModal: NgbActiveModal,
|
||||
protected language: LanguageStore,
|
||||
protected message: MessageService,
|
||||
protected checkTwoFactorCode: CheckTwoFactorCode
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public checkCode() {
|
||||
const authCode = this.authCode;
|
||||
|
||||
this.checkTwoFactorCode.checkCode(authCode).subscribe({
|
||||
next: (response) => {
|
||||
this.closeModal(response.data.two_factor_complete)
|
||||
},
|
||||
error: () => {
|
||||
this.message.addDangerMessageByKey('LBL_FACTOR_AUTH_FAIL')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public closeModal(authComplete: boolean) {
|
||||
this.activeModal.close({
|
||||
two_factor_complete: authComplete
|
||||
} as TwoFactorCheckModalResult);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2024 SalesAgility Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
|
||||
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License
|
||||
* version 3, these Appropriate Legal Notices must retain the display of the
|
||||
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
|
||||
* feasible for technical reasons, the Appropriate Legal Notices must display
|
||||
* the words "Supercharged by SuiteCRM".
|
||||
*/
|
||||
|
||||
export interface TwoFactorCheckModalResult {
|
||||
[key: string]: any;
|
||||
|
||||
two_factor_complete: boolean
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2024 SalesAgility Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
|
||||
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License
|
||||
* version 3, these Appropriate Legal Notices must retain the display of the
|
||||
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
|
||||
* feasible for technical reasons, the Appropriate Legal Notices must display
|
||||
* the words "Supercharged by SuiteCRM".
|
||||
*/
|
||||
|
||||
import {NgModule} from "@angular/core";
|
||||
import {CommonModule} from "@angular/common";
|
||||
import {ModalModule} from "../../../../components/modal/components/modal/modal.module";
|
||||
import {TwoFactorCheckModalComponent} from "./2fa-check-modal.component";
|
||||
import {TwoFactorCheckModule} from "../2fa-check/2fa-check.module";
|
||||
import {FormsModule} from "@angular/forms";
|
||||
import {LabelModule} from "../../../../components/label/label.module";
|
||||
import {TrustHtmlModule} from "../../../../pipes/trust-html/trust-html.module";
|
||||
|
||||
@NgModule({
|
||||
declarations: [TwoFactorCheckModalComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
ModalModule,
|
||||
TwoFactorCheckModule,
|
||||
FormsModule,
|
||||
LabelModule,
|
||||
TrustHtmlModule,
|
||||
]
|
||||
})
|
||||
export class TwoFactorCheckModalModule {
|
||||
}
|
|
@ -34,6 +34,8 @@ import {ButtonCallback, ButtonInterface} from "../../../../common/components/but
|
|||
import {UserPreferenceStore} from "../../../../store/user-preference/user-preference.store";
|
||||
import {Clipboard} from '@angular/cdk/clipboard';
|
||||
import {GenerateBackupCodes} from "../../../../services/process/processes/generate-backup-codes/generate-backup-codes";
|
||||
import {NgbModal} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {TwoFactorCheckModalComponent} from "../2fa-check-modal/2fa-check-modal.component";
|
||||
|
||||
|
||||
@Component({
|
||||
|
@ -70,6 +72,7 @@ export class TwoFactorComponent implements OnInit {
|
|||
protected message: MessageService,
|
||||
protected language: LanguageStore,
|
||||
protected userPreference: UserPreferenceStore,
|
||||
protected modalService: NgbModal,
|
||||
protected clipboard: Clipboard,
|
||||
protected generateBackupCodesService: GenerateBackupCodes,
|
||||
) {
|
||||
|
@ -117,7 +120,7 @@ export class TwoFactorComponent implements OnInit {
|
|||
onClick: ((): void => {
|
||||
this.generateBackupCodes();
|
||||
}) as ButtonCallback,
|
||||
labelKey: 'LBL_REGENERATE_BACKUP_CODES',
|
||||
labelKey: 'LBL_REGENERATE_CODES',
|
||||
titleKey: ''
|
||||
} as ButtonInterface;
|
||||
}
|
||||
|
@ -140,35 +143,46 @@ export class TwoFactorComponent implements OnInit {
|
|||
}
|
||||
|
||||
public disable2FactorAuth(): void {
|
||||
this.authService.disable2fa().subscribe({
|
||||
next: (response) => {
|
||||
if (isTrue(response?.two_factor_disabled)) {
|
||||
const modal = this.modalService.open(TwoFactorCheckModalComponent, {size: 'lg'});
|
||||
|
||||
this.isAppMethodEnabled.set(false);
|
||||
this.areRecoveryCodesGenerated.set(false);
|
||||
this.isQrCodeGenerated.set(false);
|
||||
|
||||
this.message.addSuccessMessageByKey('LBL_FACTOR_AUTH_DISABLE');
|
||||
}
|
||||
},
|
||||
error: () => {
|
||||
this.isAppMethodEnabled.set(true);
|
||||
this.areRecoveryCodesGenerated.set(true);
|
||||
modal.result.then((result) => {
|
||||
if (!result.two_factor_complete){
|
||||
this.message.addDangerMessageByKey('LBL_FACTOR_AUTH_FAIL');
|
||||
return;
|
||||
}
|
||||
});
|
||||
return;
|
||||
|
||||
this.authService.disable2fa().subscribe({
|
||||
next: (response) => {
|
||||
if (isTrue(response?.two_factor_disabled)) {
|
||||
|
||||
this.isAppMethodEnabled.set(false);
|
||||
this.areRecoveryCodesGenerated.set(false);
|
||||
this.isQrCodeGenerated.set(false);
|
||||
|
||||
this.message.addSuccessMessageByKey('LBL_FACTOR_AUTH_DISABLE');
|
||||
}
|
||||
},
|
||||
error: () => {
|
||||
this.isAppMethodEnabled.set(true);
|
||||
this.areRecoveryCodesGenerated.set(true);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}).catch();
|
||||
|
||||
}
|
||||
|
||||
getTitle(): string {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
public finalize2fa() {
|
||||
public finalize2fa(): void {
|
||||
this.authService.finalize2fa(this.authCode).subscribe(response => {
|
||||
const verified = response?.two_factor_setup_complete ?? false;
|
||||
|
||||
if (isTrue(verified)) {
|
||||
this.generateBackupCodes();
|
||||
this.generateCodes();
|
||||
this.message.addSuccessMessageByKey('LBL_FACTOR_AUTH_SUCCESS');
|
||||
|
||||
this.isAppMethodEnabled.set(true);
|
||||
|
@ -182,24 +196,36 @@ export class TwoFactorComponent implements OnInit {
|
|||
})
|
||||
}
|
||||
|
||||
public copyBackupCodes() {
|
||||
public copyBackupCodes(): void {
|
||||
this.clipboard.copy(this.backupCodes);
|
||||
}
|
||||
|
||||
|
||||
public generateBackupCodes(){
|
||||
this.areRecoveryCodesGenerated.set(false)
|
||||
public generateCodes(): void {
|
||||
this.generateBackupCodesService.generate().subscribe({
|
||||
next: (response) => {
|
||||
console.log(response);
|
||||
console.log('inside next');
|
||||
this.backupCodes = response?.data.backupCodes;
|
||||
this.areRecoveryCodesGenerated.set(true)
|
||||
},
|
||||
error: () => {
|
||||
console.log('inside eror');
|
||||
this.areRecoveryCodesGenerated.set(false)
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
public generateBackupCodes(): void {
|
||||
|
||||
const modal = this.modalService.open(TwoFactorCheckModalComponent, {size: 'lg'});
|
||||
|
||||
modal.result.then((result) => {
|
||||
if (!result.two_factor_complete){
|
||||
this.message.addDangerMessageByKey('LBL_FACTOR_AUTH_FAIL');
|
||||
return;
|
||||
}
|
||||
|
||||
this.areRecoveryCodesGenerated.set(false)
|
||||
this.generateCodes()
|
||||
}).catch();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,30 @@
|
|||
.two-factor-popup {
|
||||
.auth-input {
|
||||
border: .03em solid $nepal-grey;
|
||||
padding: .45em;
|
||||
margin: 0 1em 0 0;
|
||||
color: #666;
|
||||
font-size: .8em;
|
||||
background-color: #fff;
|
||||
width: 30%;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 991px) {
|
||||
.backup-codes-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
gap: 10px;
|
||||
|
||||
.backup-codes {
|
||||
padding: 10px;
|
||||
border: 1px solid lightgrey;
|
||||
border-radius: .25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
#two-factor {
|
||||
|
||||
|
@ -8,6 +35,7 @@
|
|||
width: fit-content;
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
|
||||
.qr-code-container {
|
||||
display: flex;
|
||||
padding: .25rem 1.5rem .5rem 1.5rem;
|
||||
|
@ -39,15 +67,17 @@
|
|||
}
|
||||
}
|
||||
|
||||
.backup-codes-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
gap: 10px;
|
||||
@media (max-width: 991px) {
|
||||
.backup-codes-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 10px;
|
||||
|
||||
.backup-codes {
|
||||
padding: 10px;
|
||||
border: 1px solid lightgrey;
|
||||
border-radius: .25rem;
|
||||
.backup-codes {
|
||||
padding: 10px;
|
||||
border: 1px solid lightgrey;
|
||||
border-radius: .25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,6 +98,7 @@
|
|||
margin-left: 1.5rem;
|
||||
margin-right: 2rem;
|
||||
}
|
||||
|
||||
.qr-code-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -122,6 +153,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media(max-width: 374px) {
|
||||
#two-factor {
|
||||
|
||||
|
@ -132,6 +164,7 @@
|
|||
margin-left: 1.5rem;
|
||||
margin-right: 2rem;
|
||||
}
|
||||
|
||||
.qr-code-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
130
core/backend/Process/LegacyHandler/CheckTwoFactorCodeHandler.php
Normal file
130
core/backend/Process/LegacyHandler/CheckTwoFactorCodeHandler.php
Normal file
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2024 SalesAgility Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
|
||||
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License
|
||||
* version 3, these Appropriate Legal Notices must retain the display of the
|
||||
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
|
||||
* feasible for technical reasons, the Appropriate Legal Notices must display
|
||||
* the words "Supercharged by SuiteCRM".
|
||||
*/
|
||||
|
||||
namespace App\Process\LegacyHandler;
|
||||
|
||||
use ApiPlatform\Exception\InvalidArgumentException;
|
||||
use App\Engine\LegacyHandler\LegacyHandler;
|
||||
use App\Engine\LegacyHandler\LegacyScopeState;
|
||||
use App\Process\Entity\Process;
|
||||
use App\Process\Service\ProcessHandlerInterface;
|
||||
use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\Totp\TotpAuthenticatorInterface;
|
||||
use Symfony\Bundle\SecurityBundle\Security;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
class CheckTwoFactorCodeHandler extends LegacyHandler implements ProcessHandlerInterface
|
||||
{
|
||||
protected const MSG_OPTIONS_NOT_FOUND = 'Process options is not defined';
|
||||
protected const PROCESS_TYPE = 'check-two-factor-code';
|
||||
|
||||
|
||||
protected TotpAuthenticatorInterface $totpAuthenticator;
|
||||
protected Security $security;
|
||||
|
||||
|
||||
public function __construct(
|
||||
string $projectDir,
|
||||
string $legacyDir,
|
||||
string $legacySessionName,
|
||||
string $defaultSessionName,
|
||||
LegacyScopeState $legacyScopeState,
|
||||
RequestStack $requestStack,
|
||||
Security $security,
|
||||
TotpAuthenticatorInterface $totpAuthenticator,
|
||||
) {
|
||||
parent::__construct(
|
||||
$projectDir,
|
||||
$legacyDir,
|
||||
$legacySessionName,
|
||||
$defaultSessionName,
|
||||
$legacyScopeState,
|
||||
$requestStack
|
||||
);
|
||||
$this->security = $security;
|
||||
$this->totpAuthenticator = $totpAuthenticator;
|
||||
}
|
||||
|
||||
public function getHandlerKey(): string
|
||||
{
|
||||
return self::PROCESS_TYPE;
|
||||
}
|
||||
|
||||
public function getProcessType(): string
|
||||
{
|
||||
return self::PROCESS_TYPE;
|
||||
}
|
||||
|
||||
public function requiredAuthRole(): string
|
||||
{
|
||||
return 'ROLE_USER';
|
||||
}
|
||||
|
||||
public function getRequiredACLs(Process $process): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function configure(Process $process): void
|
||||
{
|
||||
$process->setId(self::PROCESS_TYPE);
|
||||
$process->setAsync(false);
|
||||
}
|
||||
|
||||
public function validate(Process $process): void
|
||||
{
|
||||
if (empty($process->getOptions())) {
|
||||
throw new InvalidArgumentException(self::MSG_OPTIONS_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
public function run(Process $process): void
|
||||
{
|
||||
$options = $process->getOptions();
|
||||
|
||||
$authCode = $options['auth_code'] ?? false;
|
||||
|
||||
$user = $this->security->getToken()->getUser();
|
||||
|
||||
if (!$options['auth_code']) {
|
||||
$process->setStatus('error');
|
||||
$process->setMessages(['LBL_ACTION_ERROR']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$correctCode = $this->totpAuthenticator->checkCode($user, $authCode);
|
||||
|
||||
if (!$correctCode){
|
||||
$correctCode = $user->isBackupCode($authCode);
|
||||
}
|
||||
|
||||
$response = ['two_factor_complete' => $correctCode];
|
||||
|
||||
$process->setData($response);
|
||||
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue