mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-25 16:59:17 +01:00
call api to set password with key parameters (#609)
* call api to set password with key parameters * update ssoCompleteRegistration string
This commit is contained in:
parent
1fe7554818
commit
e0ede7ba74
2
jslib
2
jslib
@ -1 +1 @@
|
||||
Subproject commit ed6978baff5b129341bd46cc90a6155c1bcc5124
|
||||
Subproject commit 7bf00b4fb37d85d8ffe7aa3248bd72f304297331
|
@ -1,45 +1,81 @@
|
||||
<div class="secondary-header">
|
||||
<h1>{{'setMasterPassword' | i18n}}</h1>
|
||||
</div>
|
||||
<app-callout type="tip">{{'ssoCompleteRegistration' | i18n}}</app-callout>
|
||||
<app-callout type="info" *ngIf="enforcedPolicyOptions">
|
||||
{{'masterPasswordPolicyInEffect' | i18n}}
|
||||
<ul class="mb-0">
|
||||
<li *ngIf="enforcedPolicyOptions?.minComplexity > 0">
|
||||
{{'policyInEffectMinComplexity' | i18n : getPasswordScoreAlertDisplay()}}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.minLength > 0">
|
||||
{{'policyInEffectMinLength' | i18n : enforcedPolicyOptions?.minLength.toString()}}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireUpper">{{'policyInEffectUppercase' | i18n}}</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireLower">{{'policyInEffectLowercase' | i18n}}</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireNumbers">{{'policyInEffectNumbers' | i18n}}</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireSpecial">{{'policyInEffectSpecial' | i18n : '!@#$%^&*'}}</li>
|
||||
</ul>
|
||||
</app-callout>
|
||||
|
||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate autocomplete="off">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="newMasterPassword">{{'newMasterPass' | i18n}}</label>
|
||||
<input id="newMasterPassword" type="password" name="NewMasterPasswordHash" class="form-control mb-1"
|
||||
[(ngModel)]="newMasterPassword" (input)="updatePasswordStrength()" required appInputVerbatim
|
||||
autocomplete="new-password">
|
||||
<app-password-strength [score]="masterPasswordScore" [showText]="true"></app-password-strength>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="confirmNewMasterPassword">{{'confirmNewMasterPass' | i18n}}</label>
|
||||
<input id="confirmNewMasterPassword" type="password" name="ConfirmNewMasterPasswordHash"
|
||||
class="form-control" [(ngModel)]="confirmNewMasterPassword" required appInputVerbatim
|
||||
autocomplete="new-password">
|
||||
<div class="row justify-content-md-center mt-5">
|
||||
<div class="col-5">
|
||||
<p class="lead text-center mb-4">{{'setMasterPassword' | i18n}}</p>
|
||||
<div class="card d-block">
|
||||
<div class="card-body">
|
||||
<app-callout type="info">{{'ssoCompleteRegistration' | i18n}}</app-callout>
|
||||
<div class="form-group">
|
||||
<app-callout type="info" *ngIf="enforcedPolicyOptions">
|
||||
{{'masterPasswordPolicyInEffect' | i18n}}
|
||||
<ul class="mb-0">
|
||||
<li *ngIf="enforcedPolicyOptions?.minComplexity > 0">
|
||||
{{'policyInEffectMinComplexity' | i18n : getPasswordScoreAlertDisplay()}}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.minLength > 0">
|
||||
{{'policyInEffectMinLength' | i18n : enforcedPolicyOptions?.minLength.toString()}}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireUpper">
|
||||
{{'policyInEffectUppercase' | i18n}}</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireLower">
|
||||
{{'policyInEffectLowercase' | i18n}}</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireNumbers">
|
||||
{{'policyInEffectNumbers' | i18n}}</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireSpecial">
|
||||
{{'policyInEffectSpecial' | i18n : '!@#$%^&*'}}</li>
|
||||
</ul>
|
||||
</app-callout>
|
||||
<label for="masterPassword">{{'masterPass' | i18n}}</label>
|
||||
<div class="d-flex">
|
||||
<div class="w-100">
|
||||
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}"
|
||||
name="MasterPasswordHash" class="text-monospace form-control mb-1"
|
||||
[(ngModel)]="masterPassword" (input)="updatePasswordStrength()" required
|
||||
appInputVerbatim>
|
||||
<app-password-strength [score]="masterPasswordScore" [showText]="true">
|
||||
</app-password-strength>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" class="ml-1 btn btn-link"
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(false)">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</button>
|
||||
<div class="progress-bar invisible"></div>
|
||||
</div>
|
||||
</div>
|
||||
<small class="form-text text-muted">{{'masterPassDesc' | i18n}}</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="masterPasswordRetype">{{'reTypeMasterPass' | i18n}}</label>
|
||||
<div class="d-flex">
|
||||
<input id="masterPasswordRetype" type="{{showPassword ? 'text' : 'password'}}"
|
||||
name="MasterPasswordRetype" class="text-monospace form-control"
|
||||
[(ngModel)]="masterPasswordRetype" required appInputVerbatim>
|
||||
<button type="button" class="ml-1 btn btn-link" appA11yTitle="{{'toggleVisibility' | i18n}}"
|
||||
(click)="togglePassword(true)">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="hint">{{'masterPassHint' | i18n}}</label>
|
||||
<input id="hint" class="form-control" type="text" name="Hint" [(ngModel)]="hint">
|
||||
<small class="form-text text-muted">{{'masterPassHintDesc' | i18n}}</small>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="d-flex">
|
||||
<button type="submit" class="btn btn-primary btn-block btn-submit" [disabled]="form.loading">
|
||||
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
|
||||
<span>{{'submit' | i18n}}</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-block ml-2 mt-0" (click)="logOut()">
|
||||
{{'logOut' | i18n}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
|
||||
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
|
||||
<span>{{'setMasterPassword' | i18n}}</span>
|
||||
</button>
|
||||
</form>
|
||||
|
@ -19,19 +19,25 @@ import { UserService } from 'jslib/abstractions/user.service';
|
||||
import { CipherString } from 'jslib/models/domain/cipherString';
|
||||
import { SymmetricCryptoKey } from 'jslib/models/domain/symmetricCryptoKey';
|
||||
|
||||
import { KeysRequest } from 'jslib/models/request/keysRequest';
|
||||
import { SetPasswordRequest } from 'jslib/models/request/setPasswordRequest';
|
||||
|
||||
import {
|
||||
ChangePasswordComponent as BaseChangePasswordComponent,
|
||||
} from 'jslib/angular/components/change-password.component';
|
||||
|
||||
import { KdfType } from 'jslib/enums/kdfType';
|
||||
|
||||
@Component({
|
||||
selector: 'app-accounts-change-password',
|
||||
templateUrl: 'change-password.component.html',
|
||||
})
|
||||
export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
showPassword: boolean = false;
|
||||
hint: string = '';
|
||||
|
||||
onSuccessfulChangePassword: () => Promise<any>;
|
||||
successRoute = 'lock';
|
||||
successRoute = 'vault';
|
||||
|
||||
constructor(apiService: ApiService, i18nService: I18nService,
|
||||
cryptoService: CryptoService, messagingService: MessagingService,
|
||||
@ -43,16 +49,36 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
platformUtilsService, folderService, cipherService, syncService, policyService, router);
|
||||
}
|
||||
|
||||
async performSubmitActions(newMasterPasswordHash: string, newKey: SymmetricCryptoKey,
|
||||
newEncKey: [SymmetricCryptoKey, CipherString]) {
|
||||
const setRequest = new SetPasswordRequest();
|
||||
setRequest.newMasterPasswordHash = newMasterPasswordHash;
|
||||
setRequest.key = newEncKey[1].encryptedString;
|
||||
async setupSubmitActions() {
|
||||
this.kdf = KdfType.PBKDF2_SHA256;
|
||||
const useLowerKdf = this.platformUtilsService.isEdge() || this.platformUtilsService.isIE();
|
||||
this.kdfIterations = useLowerKdf ? 10000 : 100000;
|
||||
return true;
|
||||
}
|
||||
|
||||
async performSubmitActions(masterPasswordHash: string, key: SymmetricCryptoKey,
|
||||
encKey: [SymmetricCryptoKey, CipherString]) {
|
||||
const request = new SetPasswordRequest();
|
||||
request.masterPasswordHash = masterPasswordHash;
|
||||
request.key = encKey[1].encryptedString;
|
||||
request.masterPasswordHint = this.hint;
|
||||
request.kdf = this.kdf;
|
||||
request.kdfIterations = this.kdfIterations;
|
||||
|
||||
const keys = await this.cryptoService.makeKeyPair(encKey[0]);
|
||||
request.keys = new KeysRequest(keys[0], keys[1].encryptedString);
|
||||
|
||||
try {
|
||||
this.formPromise = this.apiService.setPassword(setRequest);
|
||||
this.formPromise = this.apiService.setPassword(request);
|
||||
await this.formPromise;
|
||||
|
||||
await this.userService.setInformation(await this.userService.getUserId(), await this.userService.getEmail(),
|
||||
this.kdf, this.kdfIterations);
|
||||
await this.cryptoService.setKey(key);
|
||||
await this.cryptoService.setKeyHash(masterPasswordHash);
|
||||
await this.cryptoService.setEncKey(encKey[1].encryptedString);
|
||||
await this.cryptoService.setEncPrivateKey(keys[1].encryptedString);
|
||||
|
||||
if (this.onSuccessfulChangePassword != null) {
|
||||
this.onSuccessfulChangePassword();
|
||||
} else {
|
||||
@ -62,4 +88,10 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
this.platformUtilsService.showToast('error', null, this.i18nService.t('errorOccurred'));
|
||||
}
|
||||
}
|
||||
|
||||
togglePassword(confirmField: boolean) {
|
||||
this.platformUtilsService.eventTrack('Toggled Master Password on Set Password');
|
||||
this.showPassword = !this.showPassword;
|
||||
document.getElementById(confirmField ? 'masterPasswordRetype' : 'masterPassword').focus();
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +108,6 @@ const routes: Routes = [
|
||||
},
|
||||
{
|
||||
path: 'change-password', component: ChangePasswordComponent,
|
||||
canActivate: [UnauthGuardService],
|
||||
data: { titleId: 'setMasterPassword' },
|
||||
},
|
||||
{
|
||||
|
@ -28,18 +28,18 @@
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="newMasterPassword">{{'newMasterPass' | i18n}}</label>
|
||||
<input id="newMasterPassword" type="password" name="NewMasterPasswordHash" class="form-control mb-1"
|
||||
[(ngModel)]="newMasterPassword" (input)="updatePasswordStrength()" required appInputVerbatim
|
||||
<label for="masterPassword">{{'newMasterPass' | i18n}}</label>
|
||||
<input id="masterPassword" type="password" name="NewMasterPasswordHash" class="form-control mb-1"
|
||||
[(ngModel)]="masterPassword" (input)="updatePasswordStrength()" required appInputVerbatim
|
||||
autocomplete="new-password">
|
||||
<app-password-strength [score]="masterPasswordScore" [showText]="true"></app-password-strength>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
<label for="confirmNewMasterPassword">{{'confirmNewMasterPass' | i18n}}</label>
|
||||
<input id="confirmNewMasterPassword" type="password" name="ConfirmNewMasterPasswordHash"
|
||||
class="form-control" [(ngModel)]="confirmNewMasterPassword" required appInputVerbatim
|
||||
<label for="masterPasswordRetype">{{'confirmNewMasterPass' | i18n}}</label>
|
||||
<input id="masterPasswordRetype" type="password" name="MasterPasswordRetype"
|
||||
class="form-control" [(ngModel)]="masterPasswordRetype" required appInputVerbatim
|
||||
autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
|
@ -79,6 +79,16 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
}
|
||||
}
|
||||
|
||||
async submit() {
|
||||
const hasEncKey = await this.cryptoService.hasEncKey();
|
||||
if (!hasEncKey) {
|
||||
this.platformUtilsService.showToast('error', null, this.i18nService.t('updateKey'));
|
||||
return;
|
||||
}
|
||||
|
||||
await super.submit();
|
||||
}
|
||||
|
||||
async setupSubmitActions() {
|
||||
if (this.currentMasterPassword == null || this.currentMasterPassword === '') {
|
||||
this.platformUtilsService.showToast('error', this.i18nService.t('errorOccurred'),
|
||||
@ -90,7 +100,7 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
await this.syncService.fullSync(true);
|
||||
}
|
||||
|
||||
super.setupSubmitActions();
|
||||
return super.setupSubmitActions();
|
||||
}
|
||||
|
||||
async performSubmitActions(newMasterPasswordHash: string, newKey: SymmetricCryptoKey,
|
||||
|
@ -3168,7 +3168,7 @@
|
||||
"message": "Set Master Password"
|
||||
},
|
||||
"ssoCompleteRegistration": {
|
||||
"message": "In order to complete logging in with SSO, please set a master password below. Make sure to choose a strong password/passphrase and comply with all applied organizational policies."
|
||||
"message": "In order to complete logging in with SSO, please set a master password to access and protect your vault."
|
||||
},
|
||||
"identifier": {
|
||||
"message": "Identifier"
|
||||
|
Loading…
Reference in New Issue
Block a user