1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-09-16 02:27:00 +02: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:
Vincent Salucci 2020-03-10 12:50:54 -05:00 committed by GitHub
parent 44b86f5dd0
commit ee8ca0beed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 9 deletions

View File

@ -19,7 +19,6 @@ export class PasswordGeneratorComponent implements OnInit {
password: string = '-';
showOptions = false;
avoidAmbiguous = false;
policyInEffect = false;
enforcedPolicyOptions: PasswordGeneratorPolicyOptions;
constructor(protected passwordGenerationService: PasswordGenerationService,
@ -30,14 +29,6 @@ export class PasswordGeneratorComponent implements OnInit {
const optionsResponse = await this.passwordGenerationService.getOptions();
this.options = optionsResponse[0];
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.options.type = this.options.type === 'passphrase' ? 'passphrase' : 'password';
this.password = await this.passwordGenerationService.generatePassword(this.options);
@ -147,6 +138,10 @@ export class PasswordGeneratorComponent implements OnInit {
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) {
this.options.wordSeparator = this.options.wordSeparator[0];
}

View File

@ -1,6 +1,7 @@
import Domain from './domainBase';
export class PasswordGeneratorPolicyOptions extends Domain {
defaultType: string = '';
minLength: number = 0;
useUppercase: boolean = false;
useLowercase: boolean = false;
@ -8,4 +9,21 @@ export class PasswordGeneratorPolicyOptions extends Domain {
numberCount: number = 0;
useSpecial: boolean = false;
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;
}
}

View File

@ -262,6 +262,24 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr
if (options.minSpecial + options.minNumber > options.length) {
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
enforcedPolicyOptions = new PasswordGeneratorPolicyOptions();
}
@ -285,6 +303,11 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr
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
&& currentPolicy.data.minLength > enforcedOptions.minLength) {
enforcedOptions.minLength = currentPolicy.data.minLength;
@ -315,6 +338,19 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr
&& currentPolicy.data.minSpecial > enforcedOptions.specialCount) {
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;