mirror of
https://github.com/bitwarden/browser.git
synced 2025-02-11 00:31:45 +01:00
Password Generator Passphrase Policy (#85)
* Initial commit for passphrase enforcement * Updated type implementation * Updated default type conditional * Added helper method to enforced options object Co-authored-by: Vincent Salucci <vsalucci@bitwarden.com>
This commit is contained in:
parent
44b86f5dd0
commit
ee8ca0beed
@ -19,7 +19,6 @@ export class PasswordGeneratorComponent implements OnInit {
|
|||||||
password: string = '-';
|
password: string = '-';
|
||||||
showOptions = false;
|
showOptions = false;
|
||||||
avoidAmbiguous = false;
|
avoidAmbiguous = false;
|
||||||
policyInEffect = false;
|
|
||||||
enforcedPolicyOptions: PasswordGeneratorPolicyOptions;
|
enforcedPolicyOptions: PasswordGeneratorPolicyOptions;
|
||||||
|
|
||||||
constructor(protected passwordGenerationService: PasswordGenerationService,
|
constructor(protected passwordGenerationService: PasswordGenerationService,
|
||||||
@ -30,14 +29,6 @@ export class PasswordGeneratorComponent implements OnInit {
|
|||||||
const optionsResponse = await this.passwordGenerationService.getOptions();
|
const optionsResponse = await this.passwordGenerationService.getOptions();
|
||||||
this.options = optionsResponse[0];
|
this.options = optionsResponse[0];
|
||||||
this.enforcedPolicyOptions = optionsResponse[1];
|
this.enforcedPolicyOptions = optionsResponse[1];
|
||||||
this.policyInEffect = this.enforcedPolicyOptions != null && (
|
|
||||||
this.enforcedPolicyOptions.minLength > 0 ||
|
|
||||||
this.enforcedPolicyOptions.numberCount > 0 ||
|
|
||||||
this.enforcedPolicyOptions.specialCount > 0 ||
|
|
||||||
this.enforcedPolicyOptions.useUppercase ||
|
|
||||||
this.enforcedPolicyOptions.useLowercase ||
|
|
||||||
this.enforcedPolicyOptions.useNumbers ||
|
|
||||||
this.enforcedPolicyOptions.useSpecial);
|
|
||||||
this.avoidAmbiguous = !this.options.ambiguous;
|
this.avoidAmbiguous = !this.options.ambiguous;
|
||||||
this.options.type = this.options.type === 'passphrase' ? 'passphrase' : 'password';
|
this.options.type = this.options.type === 'passphrase' ? 'passphrase' : 'password';
|
||||||
this.password = await this.passwordGenerationService.generatePassword(this.options);
|
this.password = await this.passwordGenerationService.generatePassword(this.options);
|
||||||
@ -147,6 +138,10 @@ export class PasswordGeneratorComponent implements OnInit {
|
|||||||
this.options.numWords = 20;
|
this.options.numWords = 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.options.numWords < this.enforcedPolicyOptions.minNumberWords) {
|
||||||
|
this.options.numWords = this.enforcedPolicyOptions.minNumberWords;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.options.wordSeparator != null && this.options.wordSeparator.length > 1) {
|
if (this.options.wordSeparator != null && this.options.wordSeparator.length > 1) {
|
||||||
this.options.wordSeparator = this.options.wordSeparator[0];
|
this.options.wordSeparator = this.options.wordSeparator[0];
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import Domain from './domainBase';
|
import Domain from './domainBase';
|
||||||
|
|
||||||
export class PasswordGeneratorPolicyOptions extends Domain {
|
export class PasswordGeneratorPolicyOptions extends Domain {
|
||||||
|
defaultType: string = '';
|
||||||
minLength: number = 0;
|
minLength: number = 0;
|
||||||
useUppercase: boolean = false;
|
useUppercase: boolean = false;
|
||||||
useLowercase: boolean = false;
|
useLowercase: boolean = false;
|
||||||
@ -8,4 +9,21 @@ export class PasswordGeneratorPolicyOptions extends Domain {
|
|||||||
numberCount: number = 0;
|
numberCount: number = 0;
|
||||||
useSpecial: boolean = false;
|
useSpecial: boolean = false;
|
||||||
specialCount: number = 0;
|
specialCount: number = 0;
|
||||||
|
minNumberWords: number = 0;
|
||||||
|
capitalize: boolean = false;
|
||||||
|
includeNumber: boolean = false;
|
||||||
|
|
||||||
|
inEffect() {
|
||||||
|
return this.defaultType !== '' ||
|
||||||
|
this.minLength > 0 ||
|
||||||
|
this.numberCount > 0 ||
|
||||||
|
this.specialCount > 0 ||
|
||||||
|
this.useUppercase ||
|
||||||
|
this.useLowercase ||
|
||||||
|
this.useNumbers ||
|
||||||
|
this.useSpecial ||
|
||||||
|
this.minNumberWords > 0 ||
|
||||||
|
this.capitalize ||
|
||||||
|
this.includeNumber;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,6 +262,24 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr
|
|||||||
if (options.minSpecial + options.minNumber > options.length) {
|
if (options.minSpecial + options.minNumber > options.length) {
|
||||||
options.minSpecial = options.length - options.minNumber;
|
options.minSpecial = options.length - options.minNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.numWords < enforcedPolicyOptions.minNumberWords) {
|
||||||
|
options.numWords = enforcedPolicyOptions.minNumberWords;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enforcedPolicyOptions.capitalize) {
|
||||||
|
options.capitalize = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enforcedPolicyOptions.includeNumber) {
|
||||||
|
options.includeNumber = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force default type if password/passphrase selected via policy
|
||||||
|
if (enforcedPolicyOptions.defaultType === 'password' ||
|
||||||
|
enforcedPolicyOptions.defaultType === 'passphrase') {
|
||||||
|
options.type = enforcedPolicyOptions.defaultType;
|
||||||
|
}
|
||||||
} else { // UI layer expects an instantiated object to prevent more explicit null checks
|
} else { // UI layer expects an instantiated object to prevent more explicit null checks
|
||||||
enforcedPolicyOptions = new PasswordGeneratorPolicyOptions();
|
enforcedPolicyOptions = new PasswordGeneratorPolicyOptions();
|
||||||
}
|
}
|
||||||
@ -285,6 +303,11 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr
|
|||||||
enforcedOptions = new PasswordGeneratorPolicyOptions();
|
enforcedOptions = new PasswordGeneratorPolicyOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Password wins in multi-org collisions
|
||||||
|
if (currentPolicy.data.defaultType != null && enforcedOptions.defaultType !== 'password') {
|
||||||
|
enforcedOptions.defaultType = currentPolicy.data.defaultType;
|
||||||
|
}
|
||||||
|
|
||||||
if (currentPolicy.data.minLength != null
|
if (currentPolicy.data.minLength != null
|
||||||
&& currentPolicy.data.minLength > enforcedOptions.minLength) {
|
&& currentPolicy.data.minLength > enforcedOptions.minLength) {
|
||||||
enforcedOptions.minLength = currentPolicy.data.minLength;
|
enforcedOptions.minLength = currentPolicy.data.minLength;
|
||||||
@ -315,6 +338,19 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr
|
|||||||
&& currentPolicy.data.minSpecial > enforcedOptions.specialCount) {
|
&& currentPolicy.data.minSpecial > enforcedOptions.specialCount) {
|
||||||
enforcedOptions.specialCount = currentPolicy.data.minSpecial;
|
enforcedOptions.specialCount = currentPolicy.data.minSpecial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentPolicy.data.minNumberWords != null
|
||||||
|
&& currentPolicy.data.minNumberWords > enforcedOptions.minNumberWords) {
|
||||||
|
enforcedOptions.minNumberWords = currentPolicy.data.minNumberWords;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPolicy.data.capitalize) {
|
||||||
|
enforcedOptions.capitalize = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPolicy.data.includeNumber) {
|
||||||
|
enforcedOptions.includeNumber = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return enforcedOptions;
|
return enforcedOptions;
|
||||||
|
Loading…
Reference in New Issue
Block a user