Added set password flow to browser based SSO
This commit is contained in:
parent
a09bd4a3fe
commit
91ce6527c0
|
@ -0,0 +1,124 @@
|
||||||
|
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||||
|
<header>
|
||||||
|
<div class="left">
|
||||||
|
<a routerLink="/home">{{'cancel' | i18n}}</a>
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
<span class="title">{{'appName' | i18n}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||||
|
<span [hidden]="form.loading">{{'login' | i18n}}</span>
|
||||||
|
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<content>
|
||||||
|
<div class="box">
|
||||||
|
<app-callout type="tip">{{'ssoCompleteRegistration' | i18n}}</app-callout>
|
||||||
|
<app-callout type="info" *ngIf="enforcedPolicyOptions">
|
||||||
|
{{'masterPasswordPolicyInEffect' | i18n}}
|
||||||
|
<ul>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-content">
|
||||||
|
<div class="box-content-row" appBoxRow>
|
||||||
|
<div class="box-content-row-flex">
|
||||||
|
<div class="row-main">
|
||||||
|
<label for="masterPassword">{{'masterPass' | i18n}}
|
||||||
|
<strong class="sub-label text-{{masterPasswordScoreColor}}"
|
||||||
|
*ngIf="masterPasswordScoreText">
|
||||||
|
{{masterPasswordScoreText}}
|
||||||
|
</strong>
|
||||||
|
</label>
|
||||||
|
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}"
|
||||||
|
name="MasterPassword" class="monospaced" [(ngModel)]="masterPassword" required
|
||||||
|
(input)="updatePasswordStrength()" appInputVerbatim>
|
||||||
|
</div>
|
||||||
|
<div class="action-buttons">
|
||||||
|
<a class="row-btn" href="#" appStopClick appBlurClick role="button"
|
||||||
|
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(false)">
|
||||||
|
<i class="fa fa-lg" aria-hidden="true"
|
||||||
|
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="progress">
|
||||||
|
<div class="progress-bar bg-{{masterPasswordScoreColor}}" role="progressbar"
|
||||||
|
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"
|
||||||
|
[ngStyle]="{width: (masterPasswordScoreWidth + '%')}"
|
||||||
|
attr.aria-valuenow="{{masterPasswordScoreWidth}}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-footer">
|
||||||
|
{{'masterPassDesc' | i18n}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-content">
|
||||||
|
<div class="box-content-row" appBoxRow>
|
||||||
|
<div class="box-content-row-flex">
|
||||||
|
<div class="row-main">
|
||||||
|
<label for="masterPasswordRetype">{{'reTypeMasterPass' | i18n}}</label>
|
||||||
|
<input id="masterPasswordRetype" type="password" name="MasterPasswordRetype"
|
||||||
|
class="monospaced" [(ngModel)]="masterPasswordRetype" required appInputVerbatim
|
||||||
|
autocomplete="new-password">
|
||||||
|
</div>
|
||||||
|
<div class="action-buttons">
|
||||||
|
<a class="row-btn" href="#" appStopClick appBlurClick role="button"
|
||||||
|
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(true)">
|
||||||
|
<i class="fa fa-lg" aria-hidden="true"
|
||||||
|
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box last">
|
||||||
|
<div class="box-content">
|
||||||
|
<div class="box-content-row" appBoxRow>
|
||||||
|
<label for="hint">{{'masterPassHint' | i18n}}</label>
|
||||||
|
<input id="hint" type="text" name="Hint" [(ngModel)]="hint">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-footer">
|
||||||
|
{{'masterPassHintDesc' | i18n}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</content>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- <div class="content">
|
||||||
|
<img class="logo-image" alt="Bitwarden">
|
||||||
|
<p class="lead">{{'setMasterPassword' | i18n}}</p>
|
||||||
|
|
||||||
|
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate autocomplete="off">
|
||||||
|
|
||||||
|
<div class="buttons">
|
||||||
|
<button type="submit" class="btn primary block" [disabled]="form.loading">
|
||||||
|
<i *ngIf="form.loading" class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}"
|
||||||
|
aria-hidden="true"></i>
|
||||||
|
<span>{{'submit' | i18n}}</span>
|
||||||
|
</button>
|
||||||
|
<button class="btn block" (click)="logOut()">
|
||||||
|
<span>{{'logOut' | i18n}}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form> -->
|
|
@ -0,0 +1,60 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
import { ApiService } from 'jslib/abstractions/api.service';
|
||||||
|
import { CryptoService } from 'jslib/abstractions/crypto.service';
|
||||||
|
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||||
|
import { MessagingService } from 'jslib/abstractions/messaging.service';
|
||||||
|
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
|
||||||
|
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
||||||
|
import { PolicyService } from 'jslib/abstractions/policy.service';
|
||||||
|
import { UserService } from 'jslib/abstractions/user.service';
|
||||||
|
|
||||||
|
import {
|
||||||
|
SetPasswordComponent as BaseSetPasswordComponent,
|
||||||
|
} from 'jslib/angular/components/set-password.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-set-password',
|
||||||
|
templateUrl: 'set-password.component.html',
|
||||||
|
})
|
||||||
|
export class SetPasswordComponent extends BaseSetPasswordComponent {
|
||||||
|
constructor(apiService: ApiService, i18nService: I18nService,
|
||||||
|
cryptoService: CryptoService, messagingService: MessagingService,
|
||||||
|
userService: UserService, passwordGenerationService: PasswordGenerationService,
|
||||||
|
platformUtilsService: PlatformUtilsService, policyService: PolicyService, router: Router) {
|
||||||
|
super(i18nService, cryptoService, messagingService, userService, passwordGenerationService,
|
||||||
|
platformUtilsService, policyService, router, apiService);
|
||||||
|
}
|
||||||
|
|
||||||
|
get masterPasswordScoreWidth() {
|
||||||
|
return this.masterPasswordScore == null ? 0 : (this.masterPasswordScore + 1) * 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
get masterPasswordScoreColor() {
|
||||||
|
switch (this.masterPasswordScore) {
|
||||||
|
case 4:
|
||||||
|
return 'success';
|
||||||
|
case 3:
|
||||||
|
return 'primary';
|
||||||
|
case 2:
|
||||||
|
return 'warning';
|
||||||
|
default:
|
||||||
|
return 'danger';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get masterPasswordScoreText() {
|
||||||
|
switch (this.masterPasswordScore) {
|
||||||
|
case 4:
|
||||||
|
return this.i18nService.t('strong');
|
||||||
|
case 3:
|
||||||
|
return this.i18nService.t('good');
|
||||||
|
case 2:
|
||||||
|
return this.i18nService.t('weak');
|
||||||
|
default:
|
||||||
|
return this.masterPasswordScore != null ? this.i18nService.t('weak') : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,6 +39,7 @@ import { GroupingsComponent } from './vault/groupings.component';
|
||||||
import { PasswordHistoryComponent } from './vault/password-history.component';
|
import { PasswordHistoryComponent } from './vault/password-history.component';
|
||||||
import { ShareComponent } from './vault/share.component';
|
import { ShareComponent } from './vault/share.component';
|
||||||
import { ViewComponent } from './vault/view.component';
|
import { ViewComponent } from './vault/view.component';
|
||||||
|
import { SetPasswordComponent } from './accounts/set-password.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
|
@ -86,6 +87,11 @@ const routes: Routes = [
|
||||||
canActivate: [LaunchGuardService],
|
canActivate: [LaunchGuardService],
|
||||||
data: { state: 'sso' },
|
data: { state: 'sso' },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'set-password',
|
||||||
|
component: SetPasswordComponent,
|
||||||
|
data: { state: 'set-password' },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'register',
|
path: 'register',
|
||||||
component: RegisterComponent,
|
component: RegisterComponent,
|
||||||
|
|
|
@ -45,6 +45,7 @@ import { GroupingsComponent } from './vault/groupings.component';
|
||||||
import { PasswordHistoryComponent } from './vault/password-history.component';
|
import { PasswordHistoryComponent } from './vault/password-history.component';
|
||||||
import { ShareComponent } from './vault/share.component';
|
import { ShareComponent } from './vault/share.component';
|
||||||
import { ViewComponent } from './vault/view.component';
|
import { ViewComponent } from './vault/view.component';
|
||||||
|
import { SetPasswordComponent } from './accounts/set-password.component';
|
||||||
|
|
||||||
import { A11yTitleDirective } from 'jslib/angular/directives/a11y-title.directive';
|
import { A11yTitleDirective } from 'jslib/angular/directives/a11y-title.directive';
|
||||||
import { ApiActionDirective } from 'jslib/angular/directives/api-action.directive';
|
import { ApiActionDirective } from 'jslib/angular/directives/api-action.directive';
|
||||||
|
@ -209,6 +210,7 @@ registerLocaleData(localeZhTw, 'zh-TW');
|
||||||
TwoFactorComponent,
|
TwoFactorComponent,
|
||||||
SsoComponent,
|
SsoComponent,
|
||||||
ViewComponent,
|
ViewComponent,
|
||||||
|
SetPasswordComponent
|
||||||
],
|
],
|
||||||
entryComponents: [],
|
entryComponents: [],
|
||||||
providers: [
|
providers: [
|
||||||
|
|
|
@ -21,7 +21,7 @@ import { AuthService as AuthServiceAbstraction } from 'jslib/abstractions/auth.s
|
||||||
import { CipherService } from 'jslib/abstractions/cipher.service';
|
import { CipherService } from 'jslib/abstractions/cipher.service';
|
||||||
import { CollectionService } from 'jslib/abstractions/collection.service';
|
import { CollectionService } from 'jslib/abstractions/collection.service';
|
||||||
import { CryptoService } from 'jslib/abstractions/crypto.service';
|
import { CryptoService } from 'jslib/abstractions/crypto.service';
|
||||||
import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service';
|
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from 'jslib/abstractions/cryptoFunction.service';
|
||||||
import { EnvironmentService } from 'jslib/abstractions/environment.service';
|
import { EnvironmentService } from 'jslib/abstractions/environment.service';
|
||||||
import { EventService } from 'jslib/abstractions/event.service';
|
import { EventService } from 'jslib/abstractions/event.service';
|
||||||
import { ExportService } from 'jslib/abstractions/export.service';
|
import { ExportService } from 'jslib/abstractions/export.service';
|
||||||
|
@ -41,7 +41,6 @@ import { TokenService } from 'jslib/abstractions/token.service';
|
||||||
import { TotpService } from 'jslib/abstractions/totp.service';
|
import { TotpService } from 'jslib/abstractions/totp.service';
|
||||||
import { UserService } from 'jslib/abstractions/user.service';
|
import { UserService } from 'jslib/abstractions/user.service';
|
||||||
import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service';
|
import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service';
|
||||||
import { WebCryptoFunctionService } from 'jslib/services/webCryptoFunction.service';
|
|
||||||
|
|
||||||
import { AutofillService } from '../../services/abstractions/autofill.service';
|
import { AutofillService } from '../../services/abstractions/autofill.service';
|
||||||
import BrowserMessagingService from '../../services/browserMessaging.service';
|
import BrowserMessagingService from '../../services/browserMessaging.service';
|
||||||
|
@ -50,6 +49,7 @@ import { AuthService } from 'jslib/services/auth.service';
|
||||||
import { ConstantsService } from 'jslib/services/constants.service';
|
import { ConstantsService } from 'jslib/services/constants.service';
|
||||||
import { SearchService } from 'jslib/services/search.service';
|
import { SearchService } from 'jslib/services/search.service';
|
||||||
import { StateService } from 'jslib/services/state.service';
|
import { StateService } from 'jslib/services/state.service';
|
||||||
|
import { WebCryptoFunctionService } from 'jslib/services/webCryptoFunction.service';
|
||||||
|
|
||||||
import { Analytics } from 'jslib/misc/analytics';
|
import { Analytics } from 'jslib/misc/analytics';
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ export const authService = new AuthService(getBgService<CryptoService>('cryptoSe
|
||||||
messagingService, getBgService<VaultTimeoutService>('vaultTimeoutService')(), null);
|
messagingService, getBgService<VaultTimeoutService>('vaultTimeoutService')(), null);
|
||||||
export const searchService = new PopupSearchService(getBgService<SearchService>('searchService')(),
|
export const searchService = new PopupSearchService(getBgService<SearchService>('searchService')(),
|
||||||
getBgService<CipherService>('cipherService')(), getBgService<PlatformUtilsService>('platformUtilsService')());
|
getBgService<CipherService>('cipherService')(), getBgService<PlatformUtilsService>('platformUtilsService')());
|
||||||
export const cryptoFunctionService: CryptoFunctionService = new WebCryptoFunctionService(window,
|
export const cryptoFunctionService = new WebCryptoFunctionService(window,
|
||||||
getBgService<PlatformUtilsService>('platformUtilsService')());
|
getBgService<PlatformUtilsService>('platformUtilsService')());
|
||||||
|
|
||||||
export function initFactory(i18nService: I18nService, storageService: StorageService,
|
export function initFactory(i18nService: I18nService, storageService: StorageService,
|
||||||
|
@ -125,7 +125,7 @@ export function initFactory(i18nService: I18nService, storageService: StorageSer
|
||||||
{ provide: AuthServiceAbstraction, useValue: authService },
|
{ provide: AuthServiceAbstraction, useValue: authService },
|
||||||
{ provide: StateServiceAbstraction, useValue: stateService },
|
{ provide: StateServiceAbstraction, useValue: stateService },
|
||||||
{ provide: SearchServiceAbstraction, useValue: searchService },
|
{ provide: SearchServiceAbstraction, useValue: searchService },
|
||||||
{ provide: CryptoFunctionService, useValue: cryptoFunctionService },
|
{ provide: CryptoFunctionServiceAbstraction, useValue: cryptoFunctionService },
|
||||||
{ provide: AuditService, useFactory: getBgService<AuditService>('auditService'), deps: [] },
|
{ provide: AuditService, useFactory: getBgService<AuditService>('auditService'), deps: [] },
|
||||||
{ provide: CipherService, useFactory: getBgService<CipherService>('cipherService'), deps: [] },
|
{ provide: CipherService, useFactory: getBgService<CipherService>('cipherService'), deps: [] },
|
||||||
{ provide: FolderService, useFactory: getBgService<FolderService>('folderService'), deps: [] },
|
{ provide: FolderService, useFactory: getBgService<FolderService>('folderService'), deps: [] },
|
||||||
|
@ -135,11 +135,6 @@ export function initFactory(i18nService: I18nService, storageService: StorageSer
|
||||||
{ provide: TokenService, useFactory: getBgService<TokenService>('tokenService'), deps: [] },
|
{ provide: TokenService, useFactory: getBgService<TokenService>('tokenService'), deps: [] },
|
||||||
{ provide: I18nService, useFactory: getBgService<I18nService>('i18nService'), deps: [] },
|
{ provide: I18nService, useFactory: getBgService<I18nService>('i18nService'), deps: [] },
|
||||||
{ provide: CryptoService, useFactory: getBgService<CryptoService>('cryptoService'), deps: [] },
|
{ provide: CryptoService, useFactory: getBgService<CryptoService>('cryptoService'), deps: [] },
|
||||||
{
|
|
||||||
provide: CryptoFunctionService,
|
|
||||||
useFactory: getBgService<CryptoFunctionService>('cryptoFunctionService'),
|
|
||||||
deps: [],
|
|
||||||
},
|
|
||||||
{ provide: EventService, useFactory: getBgService<EventService>('eventService'), deps: [] },
|
{ provide: EventService, useFactory: getBgService<EventService>('eventService'), deps: [] },
|
||||||
{ provide: PolicyService, useFactory: getBgService<PolicyService>('policyService'), deps: [] },
|
{ provide: PolicyService, useFactory: getBgService<PolicyService>('policyService'), deps: [] },
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue