Browse Source

Minor fixes for 2FA

pull/6646/head
Viacheslav Klimov 4 years ago
parent
commit
16891917ee
  1. 27
      application/src/main/java/org/thingsboard/server/service/security/auth/mfa/config/DefaultTwoFaConfigManager.java
  2. 2
      common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/PlatformTwoFaSettings.java
  3. 2
      ui-ngx/src/app/core/services/menu.service.ts
  4. 15
      ui-ngx/src/app/modules/home/pages/profile/authentication-dialog/email-auth-dialog.component.scss
  5. 14
      ui-ngx/src/app/modules/home/pages/security/security.component.ts
  6. 9
      ui-ngx/src/app/modules/login/pages/login/two-factor-auth-login.component.ts
  7. 7
      ui-ngx/src/app/shared/models/two-factor-auth.models.ts

27
application/src/main/java/org/thingsboard/server/service/security/auth/mfa/config/DefaultTwoFaConfigManager.java

@ -56,12 +56,31 @@ public class DefaultTwoFaConfigManager implements TwoFaConfigManager {
@Override @Override
public Optional<AccountTwoFaSettings> getAccountTwoFaSettings(TenantId tenantId, UserId userId) { public Optional<AccountTwoFaSettings> getAccountTwoFaSettings(TenantId tenantId, UserId userId) {
PlatformTwoFaSettings platformTwoFaSettings = getPlatformTwoFaSettings(tenantId, true).orElse(null);
return Optional.ofNullable(userAuthSettingsDao.findByUserId(userId)) return Optional.ofNullable(userAuthSettingsDao.findByUserId(userId))
.flatMap(userAuthSettings -> Optional.ofNullable(userAuthSettings.getTwoFaSettings())) .map(userAuthSettings -> {
.map(twoFaSettings -> { AccountTwoFaSettings twoFaSettings = userAuthSettings.getTwoFaSettings();
twoFaSettings.getConfigs().keySet().removeIf(providerType -> { if (twoFaSettings == null) return null;
return getTwoFaProviderConfig(tenantId, providerType).isEmpty(); boolean updateNeeded;
Map<TwoFaProviderType, TwoFaAccountConfig> configs = twoFaSettings.getConfigs();
updateNeeded = configs.keySet().removeIf(providerType -> {
return platformTwoFaSettings == null || platformTwoFaSettings.getProviderConfig(providerType).isEmpty();
}); });
if (configs.size() == 1 && configs.containsKey(TwoFaProviderType.BACKUP_CODE)) {
configs.remove(TwoFaProviderType.BACKUP_CODE);
updateNeeded = true;
}
if (!configs.isEmpty() && configs.values().stream().noneMatch(TwoFaAccountConfig::isUseByDefault)) {
configs.values().stream()
.filter(config -> config.getProviderType() != TwoFaProviderType.BACKUP_CODE)
.findFirst().ifPresent(config -> config.setUseByDefault(true));
updateNeeded = true;
}
if (updateNeeded) {
twoFaSettings = saveAccountTwoFaSettings(tenantId, userId, twoFaSettings);
}
return twoFaSettings; return twoFaSettings;
}); });
} }

2
common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/PlatformTwoFaSettings.java

@ -35,12 +35,14 @@ public class PlatformTwoFaSettings {
@NotNull @NotNull
private List<TwoFaProviderConfig> providers; private List<TwoFaProviderConfig> providers;
@NotNull
@Min(value = 5, message = "minimum verification code sent period must be greater than or equal 5") @Min(value = 5, message = "minimum verification code sent period must be greater than or equal 5")
private Integer minVerificationCodeSendPeriod; private Integer minVerificationCodeSendPeriod;
@Pattern(regexp = "[1-9]\\d*:[1-9]\\d*", message = "verification code check rate limit configuration is invalid") @Pattern(regexp = "[1-9]\\d*:[1-9]\\d*", message = "verification code check rate limit configuration is invalid")
private String verificationCodeCheckRateLimit; private String verificationCodeCheckRateLimit;
@Min(value = 0, message = "maximum number of verification failure before user lockout must be positive") @Min(value = 0, message = "maximum number of verification failure before user lockout must be positive")
private Integer maxVerificationFailuresBeforeUserLockout; private Integer maxVerificationFailuresBeforeUserLockout;
@NotNull
@Min(value = 60, message = "total amount of time allotted for verification must be greater than or equal 60") @Min(value = 60, message = "total amount of time allotted for verification must be greater than or equal 60")
private Integer totalAllowedTimeForVerification; private Integer totalAllowedTimeForVerification;

2
ui-ngx/src/app/core/services/menu.service.ts

@ -376,7 +376,7 @@ export class MenuService {
name: 'admin.system-settings', name: 'admin.system-settings',
type: 'toggle', type: 'toggle',
path: '/settings', path: '/settings',
height: '120px', height: '80px',
icon: 'settings', icon: 'settings',
pages: [ pages: [
{ {

15
ui-ngx/src/app/modules/home/pages/profile/authentication-dialog/email-auth-dialog.component.scss

@ -1,15 +0,0 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

14
ui-ngx/src/app/modules/home/pages/security/security.component.ts

@ -29,6 +29,7 @@ import { DatePipe } from '@angular/common';
import { ClipboardService } from 'ngx-clipboard'; import { ClipboardService } from 'ngx-clipboard';
import { TwoFactorAuthenticationService } from '@core/http/two-factor-authentication.service'; import { TwoFactorAuthenticationService } from '@core/http/two-factor-authentication.service';
import { import {
AccountTwoFaSettingProviders,
AccountTwoFaSettings, AccountTwoFaSettings,
BackupCodeTwoFactorAuthAccountConfig, BackupCodeTwoFactorAuthAccountConfig,
EmailTwoFactorAuthAccountConfig, EmailTwoFactorAuthAccountConfig,
@ -49,7 +50,7 @@ import { isDefinedAndNotNull } from '@core/utils';
export class SecurityComponent extends PageComponent implements OnInit, OnDestroy { export class SecurityComponent extends PageComponent implements OnInit, OnDestroy {
private readonly destroy$ = new Subject<void>(); private readonly destroy$ = new Subject<void>();
private accountConfig: AccountTwoFaSettings; private accountConfig: AccountTwoFaSettingProviders;
twoFactorAuth: FormGroup; twoFactorAuth: FormGroup;
user: User; user: User;
@ -128,12 +129,11 @@ export class SecurityComponent extends PageComponent implements OnInit, OnDestro
} }
private processTwoFactorAuthConfig(setting: AccountTwoFaSettings) { private processTwoFactorAuthConfig(setting: AccountTwoFaSettings) {
this.accountConfig = setting; this.accountConfig = setting?.configs || {};
const configs = this.accountConfig.configs;
Object.values(TwoFactorAuthProviderType).forEach(provider => { Object.values(TwoFactorAuthProviderType).forEach(provider => {
if (configs[provider]) { if (this.accountConfig[provider]) {
this.twoFactorAuth.get(provider).setValue(true); this.twoFactorAuth.get(provider).setValue(true);
if (configs[provider].useByDefault) { if (this.accountConfig[provider].useByDefault) {
this.useByDefault = provider; this.useByDefault = provider;
} }
} else { } else {
@ -216,7 +216,7 @@ export class SecurityComponent extends PageComponent implements OnInit, OnDestro
} }
generateNewBackupCode() { generateNewBackupCode() {
const codeLeft = this.accountConfig.configs[TwoFactorAuthProviderType.BACKUP_CODE].codesLeft; const codeLeft = (this.accountConfig[TwoFactorAuthProviderType.BACKUP_CODE] as BackupCodeTwoFactorAuthAccountConfig).codesLeft;
let subscription: Observable<boolean>; let subscription: Observable<boolean>;
if (codeLeft) { if (codeLeft) {
subscription = this.dialogService.confirm( subscription = this.dialogService.confirm(
@ -240,7 +240,7 @@ export class SecurityComponent extends PageComponent implements OnInit, OnDestro
providerDataInfo(provider: TwoFactorAuthProviderType) { providerDataInfo(provider: TwoFactorAuthProviderType) {
const info = {info: null}; const info = {info: null};
const providerConfig = this.accountConfig.configs[provider]; const providerConfig = this.accountConfig[provider];
if (isDefinedAndNotNull(providerConfig)) { if (isDefinedAndNotNull(providerConfig)) {
switch (provider) { switch (provider) {
case TwoFactorAuthProviderType.EMAIL: case TwoFactorAuthProviderType.EMAIL:

9
ui-ngx/src/app/modules/login/pages/login/two-factor-auth-login.component.ts

@ -29,6 +29,7 @@ import {
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { interval, Subscription } from 'rxjs'; import { interval, Subscription } from 'rxjs';
import { isEqual } from '@core/utils'; import { isEqual } from '@core/utils';
import {ActionNotificationShow} from "@core/notification/notification.actions";
@Component({ @Component({
selector: 'tb-two-factor-auth-login', selector: 'tb-two-factor-auth-login',
@ -118,6 +119,14 @@ export class TwoFactorAuthLoginComponent extends PageComponent implements OnInit
} }
this.verificationForm.get('verificationCode').setErrors(errors); this.verificationForm.get('verificationCode').setErrors(errors);
}, 5000); }, 5000);
} else {
this.store.dispatch(new ActionNotificationShow(
{
message: error.error.message,
type: 'error',
verticalPosition: 'top',
horizontalPosition: 'left'
}));
} }
} }
); );

7
ui-ngx/src/app/shared/models/two-factor-auth.models.ts

@ -88,9 +88,12 @@ export interface BackupCodeTwoFactorAuthAccountConfig extends GeneralTwoFactorAu
export type TwoFactorAuthAccountConfig = TotpTwoFactorAuthAccountConfig | SmsTwoFactorAuthAccountConfig | export type TwoFactorAuthAccountConfig = TotpTwoFactorAuthAccountConfig | SmsTwoFactorAuthAccountConfig |
EmailTwoFactorAuthAccountConfig | BackupCodeTwoFactorAuthAccountConfig; EmailTwoFactorAuthAccountConfig | BackupCodeTwoFactorAuthAccountConfig;
export interface AccountTwoFaSettings { export interface AccountTwoFaSettings {
configs: {TwoFactorAuthProviderType: TwoFactorAuthAccountConfig}; configs: AccountTwoFaSettingProviders;
}
export type AccountTwoFaSettingProviders = {
[key in TwoFactorAuthProviderType]?: TwoFactorAuthAccountConfig;
} }
export interface TwoFaProviderInfo { export interface TwoFaProviderInfo {

Loading…
Cancel
Save