mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 18:07:31 +00:00
feat: provide option to limit (T)OTP checks (#7693)
* feat: provide option to limit (T)OTP checks * fix requests in console * update errors pkg * cleanup * cleanup * improve naming of existing config
This commit is contained in:
@@ -17,17 +17,49 @@
|
||||
<div class="lockout-content">
|
||||
<div class="row">
|
||||
<div class="length-wrapper">
|
||||
<button [disabled]="(['policy.write'] | hasRole | async) === false" mat-icon-button (click)="decrementMaxAttempts()">
|
||||
<button
|
||||
[disabled]="(['policy.write'] | hasRole | async) === false"
|
||||
mat-icon-button
|
||||
(click)="decrementPasswordMaxAttempts()"
|
||||
>
|
||||
<mat-icon>remove</mat-icon>
|
||||
</button>
|
||||
<span>{{ lockoutData.maxPasswordAttempts }}</span>
|
||||
<button [disabled]="(['policy.write'] | hasRole | async) === false" mat-icon-button (click)="incrementMaxAttempts()">
|
||||
<button
|
||||
[disabled]="(['policy.write'] | hasRole | async) === false"
|
||||
mat-icon-button
|
||||
(click)="incrementPasswordMaxAttempts()"
|
||||
>
|
||||
<mat-icon>add</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="number-toggle-row">
|
||||
<span class="left-desc">{{ 'POLICY.DATA.MAXATTEMPTS' | translate }}</span>
|
||||
<span class="left-desc">{{ 'POLICY.DATA.MAXPASSWORDATTEMPTS' | translate }}</span>
|
||||
<span class="fill-space"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="length-wrapper">
|
||||
<button
|
||||
[disabled]="(['policy.write'] | hasRole | async) === false"
|
||||
mat-icon-button
|
||||
(click)="decrementOTPMaxAttempts()"
|
||||
>
|
||||
<mat-icon>remove</mat-icon>
|
||||
</button>
|
||||
<span>{{ lockoutData.maxOtpAttempts }}</span>
|
||||
<button
|
||||
[disabled]="(['policy.write'] | hasRole | async) === false"
|
||||
mat-icon-button
|
||||
(click)="incrementOTPMaxAttempts()"
|
||||
>
|
||||
<mat-icon>add</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="number-toggle-row">
|
||||
<span class="left-desc">{{ 'POLICY.DATA.MAXOTPATTEMPTS' | translate }}</span>
|
||||
<span class="fill-space"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -91,24 +91,36 @@ export class PasswordLockoutPolicyComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
public incrementMaxAttempts(): void {
|
||||
public incrementPasswordMaxAttempts(): void {
|
||||
if (this.lockoutData?.maxPasswordAttempts !== undefined) {
|
||||
this.lockoutData.maxPasswordAttempts++;
|
||||
}
|
||||
}
|
||||
|
||||
public decrementMaxAttempts(): void {
|
||||
public decrementPasswordMaxAttempts(): void {
|
||||
if (this.lockoutData?.maxPasswordAttempts && this.lockoutData?.maxPasswordAttempts > 0) {
|
||||
this.lockoutData.maxPasswordAttempts--;
|
||||
}
|
||||
}
|
||||
|
||||
public incrementOTPMaxAttempts(): void {
|
||||
if (this.lockoutData?.maxOtpAttempts !== undefined) {
|
||||
this.lockoutData.maxOtpAttempts++;
|
||||
}
|
||||
}
|
||||
|
||||
public decrementOTPMaxAttempts(): void {
|
||||
if (this.lockoutData?.maxOtpAttempts && this.lockoutData?.maxOtpAttempts > 0) {
|
||||
this.lockoutData.maxOtpAttempts--;
|
||||
}
|
||||
}
|
||||
|
||||
public savePolicy(): void {
|
||||
let promise: Promise<any>;
|
||||
if (this.lockoutData) {
|
||||
if (this.service instanceof AdminService) {
|
||||
promise = this.service
|
||||
.updateLockoutPolicy(this.lockoutData.maxPasswordAttempts)
|
||||
.updateLockoutPolicy(this.lockoutData.maxPasswordAttempts, this.lockoutData.maxOtpAttempts)
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||
this.fetchData();
|
||||
@@ -119,7 +131,7 @@ export class PasswordLockoutPolicyComponent implements OnInit {
|
||||
} else {
|
||||
if ((this.lockoutData as LockoutPolicy.AsObject).isDefault) {
|
||||
promise = (this.service as ManagementService)
|
||||
.addCustomLockoutPolicy(this.lockoutData.maxPasswordAttempts)
|
||||
.addCustomLockoutPolicy(this.lockoutData.maxPasswordAttempts, this.lockoutData.maxOtpAttempts)
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||
this.fetchData();
|
||||
@@ -129,7 +141,7 @@ export class PasswordLockoutPolicyComponent implements OnInit {
|
||||
});
|
||||
} else {
|
||||
promise = (this.service as ManagementService)
|
||||
.updateCustomLockoutPolicy(this.lockoutData.maxPasswordAttempts)
|
||||
.updateCustomLockoutPolicy(this.lockoutData.maxPasswordAttempts, this.lockoutData.maxOtpAttempts)
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||
this.fetchData();
|
||||
|
@@ -957,9 +957,13 @@ export class AdminService {
|
||||
return this.grpcService.admin.getLockoutPolicy(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public updateLockoutPolicy(maxAttempts: number): Promise<UpdateLockoutPolicyResponse.AsObject> {
|
||||
public updateLockoutPolicy(
|
||||
maxPasswordAttempts: number,
|
||||
maxOTPAttempts: number,
|
||||
): Promise<UpdateLockoutPolicyResponse.AsObject> {
|
||||
const req = new UpdateLockoutPolicyRequest();
|
||||
req.setMaxPasswordAttempts(maxAttempts);
|
||||
req.setMaxPasswordAttempts(maxPasswordAttempts);
|
||||
req.setMaxOtpAttempts(maxOTPAttempts);
|
||||
|
||||
return this.grpcService.admin.updateLockoutPolicy(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
@@ -1587,9 +1587,13 @@ export class ManagementService {
|
||||
return this.grpcService.mgmt.getLockoutPolicy(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public addCustomLockoutPolicy(maxAttempts: number): Promise<AddCustomLockoutPolicyResponse.AsObject> {
|
||||
public addCustomLockoutPolicy(
|
||||
maxPasswordAttempts: number,
|
||||
maxOTPAttempts: number,
|
||||
): Promise<AddCustomLockoutPolicyResponse.AsObject> {
|
||||
const req = new AddCustomLockoutPolicyRequest();
|
||||
req.setMaxPasswordAttempts(maxAttempts);
|
||||
req.setMaxPasswordAttempts(maxPasswordAttempts);
|
||||
req.setMaxOtpAttempts(maxOTPAttempts);
|
||||
|
||||
return this.grpcService.mgmt.addCustomLockoutPolicy(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
@@ -1599,9 +1603,13 @@ export class ManagementService {
|
||||
return this.grpcService.mgmt.resetLockoutPolicyToDefault(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
||||
public updateCustomLockoutPolicy(maxAttempts: number): Promise<UpdateCustomLockoutPolicyResponse.AsObject> {
|
||||
public updateCustomLockoutPolicy(
|
||||
maxPasswordAttempts: number,
|
||||
maxOTPAttempts: number,
|
||||
): Promise<UpdateCustomLockoutPolicyResponse.AsObject> {
|
||||
const req = new UpdateCustomLockoutPolicyRequest();
|
||||
req.setMaxPasswordAttempts(maxAttempts);
|
||||
req.setMaxPasswordAttempts(maxPasswordAttempts);
|
||||
req.setMaxOtpAttempts(maxOTPAttempts);
|
||||
|
||||
return this.grpcService.mgmt.updateCustomLockoutPolicy(req, null).then((resp) => resp.toObject());
|
||||
}
|
||||
|
@@ -1653,7 +1653,8 @@
|
||||
"HASLOWERCASE": "има малки букви",
|
||||
"HASUPPERCASE": "има главни букви",
|
||||
"SHOWLOCKOUTFAILURES": "показва грешки при блокиране",
|
||||
"MAXATTEMPTS": "Максимален брой опити за парола",
|
||||
"MAXPASSWORDATTEMPTS": "Максимален брой опити за парола",
|
||||
"MAXOTPATTEMPTS": "Максимален брой опити за OTP",
|
||||
"EXPIREWARNDAYS": "Предупреждение за изтичане след ден",
|
||||
"MAXAGEDAYS": "Максимална възраст в дни",
|
||||
"USERLOGINMUSTBEDOMAIN": "Добавяне на домейн на организация като суфикс към имената за вход",
|
||||
|
@@ -1660,7 +1660,8 @@
|
||||
"HASLOWERCASE": "obsahuje malá písmena",
|
||||
"HASUPPERCASE": "obsahuje velká písmena",
|
||||
"SHOWLOCKOUTFAILURES": "zobrazit neúspěšné pokusy o uzamčení",
|
||||
"MAXATTEMPTS": "Maximální počet pokusů o heslo",
|
||||
"MAXPASSWORDATTEMPTS": "Maximální počet pokusů o heslo",
|
||||
"MAXOTPATTEMPTS": "Maximální počet pokusů o OTP",
|
||||
"EXPIREWARNDAYS": "Upozornění na expiraci po dni",
|
||||
"MAXAGEDAYS": "Maximální stáří v dnech",
|
||||
"USERLOGINMUSTBEDOMAIN": "Přidat doménu organizace jako příponu k přihlašovacím jménům",
|
||||
|
@@ -1659,7 +1659,8 @@
|
||||
"HASLOWERCASE": "erfordert Kleinbuchstaben",
|
||||
"HASUPPERCASE": "erfordert Grossbuchstaben",
|
||||
"SHOWLOCKOUTFAILURES": "Zeige Anzahl Anmeldeversuche",
|
||||
"MAXATTEMPTS": "Maximale Anzahl an Versuchen",
|
||||
"MAXPASSWORDATTEMPTS": "Maximale Anzahl an Passwort Versuchen",
|
||||
"MAXOTPATTEMPTS": "Maximale Anzahl an OTP Versuchen",
|
||||
"EXPIREWARNDAYS": "Ablauf Warnung nach Tagen",
|
||||
"MAXAGEDAYS": "Maximale Gültigkeit in Tagen",
|
||||
"USERLOGINMUSTBEDOMAIN": "Organisationsdomain dem Loginname hinzufügen",
|
||||
|
@@ -1660,7 +1660,8 @@
|
||||
"HASLOWERCASE": "must include a lowercase letter",
|
||||
"HASUPPERCASE": "must include an uppercase letter",
|
||||
"SHOWLOCKOUTFAILURES": "show lockout failures",
|
||||
"MAXATTEMPTS": "Password maximum Attempts",
|
||||
"MAXPASSWORDATTEMPTS": "Password maximum attempts",
|
||||
"MAXOTPATTEMPTS": "OTP maximum attempts",
|
||||
"EXPIREWARNDAYS": "Expiration Warning after day",
|
||||
"MAXAGEDAYS": "Max Age in days",
|
||||
"USERLOGINMUSTBEDOMAIN": "Add organization domain as suffix to loginnames",
|
||||
|
@@ -1661,7 +1661,8 @@
|
||||
"HASLOWERCASE": "tiene minúsculas",
|
||||
"HASUPPERCASE": "tiene mayúsculas",
|
||||
"SHOWLOCKOUTFAILURES": "mostrar fallos de bloqueo",
|
||||
"MAXATTEMPTS": "Intentos máximos",
|
||||
"MAXPASSWORDATTEMPTS": "Intentos máximos de contraseña",
|
||||
"MAXOTPATTEMPTS": "Intentos máximos de OTP",
|
||||
"EXPIREWARNDAYS": "Aviso de expiración después de estos días: ",
|
||||
"MAXAGEDAYS": "Antigüedad máxima en días",
|
||||
"USERLOGINMUSTBEDOMAIN": "Añadir el dominio de la organización como sufijo de los nombres de inicio de sesión",
|
||||
|
@@ -1659,7 +1659,8 @@
|
||||
"HASLOWERCASE": "a minuscule",
|
||||
"HASUPPERCASE": "a majuscule",
|
||||
"SHOWLOCKOUTFAILURES": "montrer les échecs de verrouillage",
|
||||
"MAXATTEMPTS": "Mot de passe maximum Tentatives",
|
||||
"MAXPASSWORDATTEMPTS": "Mot de passe maximum tentatives",
|
||||
"MAXOTPATTEMPTS": "Maximal de tentatives OTP",
|
||||
"EXPIREWARNDAYS": "Expiration Avertissement après le jour",
|
||||
"MAXAGEDAYS": "Âge maximum en jours",
|
||||
"USERLOGINMUSTBEDOMAIN": "Le nom de connexion de l'utilisateur doit contenir le nom de domaine de l'organisation",
|
||||
|
@@ -1659,7 +1659,8 @@
|
||||
"HASLOWERCASE": "ha la minuscola",
|
||||
"HASUPPERCASE": "ha la maiuscola",
|
||||
"SHOWLOCKOUTFAILURES": "mostra i fallimenti del blocco",
|
||||
"MAXATTEMPTS": "Massimo numero di tentativi di password",
|
||||
"MAXPASSWORDATTEMPTS": "Massimo numero di tentativi di password",
|
||||
"MAXOTPATTEMPTS": "Massimo numero di tentativi di OTP",
|
||||
"EXPIREWARNDAYS": "Avviso scadenza dopo il giorno",
|
||||
"MAXAGEDAYS": "Lunghezza massima in giorni",
|
||||
"USERLOGINMUSTBEDOMAIN": "Nome utente deve contenere il dominio dell' organizzazione",
|
||||
|
@@ -1656,7 +1656,8 @@
|
||||
"HASLOWERCASE": "小文字を含める",
|
||||
"HASUPPERCASE": "大文字を含める",
|
||||
"SHOWLOCKOUTFAILURES": "ロックアウトの失敗を表示する",
|
||||
"MAXATTEMPTS": "パスワードの最大試行",
|
||||
"MAXPASSWORDATTEMPTS": "パスワードの最大試行",
|
||||
"MAXOTPATTEMPTS": "最大OTP試行回数",
|
||||
"EXPIREWARNDAYS": "有効期限の翌日以降の警告",
|
||||
"MAXAGEDAYS": "最大有効期限",
|
||||
"USERLOGINMUSTBEDOMAIN": "ログイン名の接尾辞として組織ドメインを追加する",
|
||||
|
@@ -1661,7 +1661,8 @@
|
||||
"HASLOWERCASE": "има мали букви",
|
||||
"HASUPPERCASE": "има големи букви",
|
||||
"SHOWLOCKOUTFAILURES": "прикажи неуспешни заклучувања",
|
||||
"MAXATTEMPTS": "Максимален број на обиди за лозинка",
|
||||
"MAXPASSWORDATTEMPTS": "Максимален број на обиди за лозинка",
|
||||
"MAXOTPATTEMPTS": "Максимални обиди за OTP",
|
||||
"EXPIREWARNDAYS": "Предупредување за истекување по ден",
|
||||
"MAXAGEDAYS": "Максимална возраст во денови",
|
||||
"USERLOGINMUSTBEDOMAIN": "Додади организациски домен како суфикс на корисничките имиња",
|
||||
|
@@ -1660,7 +1660,8 @@
|
||||
"HASLOWERCASE": "heeft kleine letters",
|
||||
"HASUPPERCASE": "heeft hoofdletters",
|
||||
"SHOWLOCKOUTFAILURES": "toon lockout mislukkingen",
|
||||
"MAXATTEMPTS": "Maximum pogingen voor wachtwoord",
|
||||
"MAXPASSWORDATTEMPTS": "Maximum pogingen voor wachtwoord",
|
||||
"MAXOTPATTEMPTS": "Maximale OTP-pogingen",
|
||||
"EXPIREWARNDAYS": "Vervaldatum Waarschuwing na dag",
|
||||
"MAXAGEDAYS": "Maximale Leeftijd in dagen",
|
||||
"USERLOGINMUSTBEDOMAIN": "Voeg organisatie domein toe als achtervoegsel aan inlognamen",
|
||||
|
@@ -1659,7 +1659,8 @@
|
||||
"HASLOWERCASE": "zawiera małe litery",
|
||||
"HASUPPERCASE": "zawiera duże litery",
|
||||
"SHOWLOCKOUTFAILURES": "pokaż blokady nieudanych prób",
|
||||
"MAXATTEMPTS": "Maksymalna liczba prób wprowadzenia hasła",
|
||||
"MAXPASSWORDATTEMPTS": "Maksymalna liczba prób wprowadzenia hasła",
|
||||
"MAXOTPATTEMPTS": "Maksymalna liczba prób OTP",
|
||||
"EXPIREWARNDAYS": "Ostrzeżenie o wygaśnięciu po dniu",
|
||||
"MAXAGEDAYS": "Maksymalny wiek w dniach",
|
||||
"USERLOGINMUSTBEDOMAIN": "Dodaj domenę organizacji jako przyrostek do nazw logowania",
|
||||
|
@@ -1661,7 +1661,8 @@
|
||||
"HASLOWERCASE": "tem letra minúscula",
|
||||
"HASUPPERCASE": "tem letra maiúscula",
|
||||
"SHOWLOCKOUTFAILURES": "mostrar falhas de bloqueio",
|
||||
"MAXATTEMPTS": "Máximo de tentativas de senha",
|
||||
"MAXPASSWORDATTEMPTS": "Máximo de tentativas de senha",
|
||||
"MAXOTPATTEMPTS": "Máximo de tentativas de OTP",
|
||||
"EXPIREWARNDAYS": "Aviso de expiração após dias",
|
||||
"MAXAGEDAYS": "Idade máxima em dias",
|
||||
"USERLOGINMUSTBEDOMAIN": "Adicionar domínio da organização como sufixo aos nomes de login",
|
||||
|
@@ -1729,7 +1729,8 @@
|
||||
"HASLOWERCASE": "Содержит нижний регистр",
|
||||
"HASUPPERCASE": "Содержит верхний регистр",
|
||||
"SHOWLOCKOUTFAILURES": "Показать ошибки блокировки",
|
||||
"MAXATTEMPTS": "Максимальное количество попыток пароля",
|
||||
"MAXPASSWORDATTEMPTS": "Максимальное количество попыток пароля",
|
||||
"MAXOTPATTEMPTS": "Максимальное количество попыток OTP",
|
||||
"EXPIREWARNDAYS": "Предупреждение об истечении срока действия после дня",
|
||||
"MAXAGEDAYS": "Максимальный возраст в днях",
|
||||
"USERLOGINMUSTBEDOMAIN": "Добавить домен организации в качестве суффикса к именам логина",
|
||||
|
@@ -1658,7 +1658,8 @@
|
||||
"HASLOWERCASE": "包含小写字母",
|
||||
"HASUPPERCASE": "包含大写字母",
|
||||
"SHOWLOCKOUTFAILURES": "显示锁定失败",
|
||||
"MAXATTEMPTS": "密码最大尝试次数",
|
||||
"MAXPASSWORDATTEMPTS": "密码最大尝试次数",
|
||||
"MAXOTPATTEMPTS": "最多尝试 OTP 次数",
|
||||
"EXPIREWARNDAYS": "密码过期警告",
|
||||
"MAXAGEDAYS": "Max Age in days",
|
||||
"USERLOGINMUSTBEDOMAIN": "用户名必须包含组织域名",
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user