Skip to content

Commit

Permalink
[SG-163] Two step login flow web (#3648)
Browse files Browse the repository at this point in the history
* two step login flow

* moved code from old branch and reafctored

* fixed review comments
  • Loading branch information
gbubemismith authored Oct 18, 2022
1 parent 65989e3 commit 9f34158
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 95 deletions.
6 changes: 6 additions & 0 deletions apps/browser/src/popup/accounts/login.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { FormBuilder } from "@angular/forms";
import { Router } from "@angular/router";

import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/components/login.component";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AppIdService } from "@bitwarden/common/abstractions/appId.service";
import { AuthService } from "@bitwarden/common/abstractions/auth.service";
import { CryptoFunctionService } from "@bitwarden/common/abstractions/cryptoFunction.service";
import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service";
Expand All @@ -22,6 +24,8 @@ export class LoginComponent extends BaseLoginComponent {
protected alwaysRememberEmail = true;

constructor(
apiService: ApiService,
appIdService: AppIdService,
authService: AuthService,
router: Router,
protected platformUtilsService: PlatformUtilsService,
Expand All @@ -37,6 +41,8 @@ export class LoginComponent extends BaseLoginComponent {
formValidationErrorService: FormValidationErrorsService
) {
super(
apiService,
appIdService,
authService,
router,
platformUtilsService,
Expand Down
6 changes: 6 additions & 0 deletions apps/desktop/src/app/accounts/login.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { Router } from "@angular/router";

import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/components/login.component";
import { ModalService } from "@bitwarden/angular/services/modal.service";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AppIdService } from "@bitwarden/common/abstractions/appId.service";
import { AuthService } from "@bitwarden/common/abstractions/auth.service";
import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
import { CryptoFunctionService } from "@bitwarden/common/abstractions/cryptoFunction.service";
Expand Down Expand Up @@ -36,6 +38,8 @@ export class LoginComponent extends BaseLoginComponent implements OnDestroy {
private deferFocus: boolean = null;

constructor(
apiService: ApiService,
appIdService: AppIdService,
authService: AuthService,
router: Router,
i18nService: I18nService,
Expand All @@ -54,6 +58,8 @@ export class LoginComponent extends BaseLoginComponent implements OnDestroy {
formValidationErrorService: FormValidationErrorsService
) {
super(
apiService,
appIdService,
authService,
router,
platformUtilsService,
Expand Down
184 changes: 96 additions & 88 deletions apps/web/src/app/accounts/login/login.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,102 +16,110 @@
<div
class="tw-mt-3 tw-rounded-md tw-border tw-border-solid tw-border-secondary-300 tw-bg-background tw-p-6"
>
<bit-callout
type="warning"
title="{{ 'resetPasswordPolicyAutoEnroll' | i18n }}"
*ngIf="showResetPasswordAutoEnrollWarning"
>
{{ "resetPasswordAutoEnrollInviteWarning" | i18n }}
</bit-callout>
<ng-container *ngIf="!validatedEmail; else loginPage">
<div class="tw-mb-3">
<bit-form-field>
<bit-label>{{ "emailAddress" | i18n }}</bit-label>
<input id="login_input_email" bitInput type="email" formControlName="email" />
</bit-form-field>
</div>

<div class="tw-mb-3">
<bit-form-field>
<bit-label>{{ "emailAddress" | i18n }}</bit-label>
<input id="login_input_email" bitInput type="email" formControlName="email" />
</bit-form-field>
</div>
<div class="tw-mb-3 tw-flex tw-items-start">
<div class="tw-flex tw-h-6 tw-items-center">
<input
id="login_input_remember-email"
class="tw-w-4 tw-rounded tw-border"
bitInput
type="checkbox"
formControlName="rememberEmail"
/>
</div>
<bit-label class="ml-2">
{{ "rememberEmail" | i18n }}
</bit-label>
</div>

<div class="tw-mb-3">
<bit-form-field>
<bit-label>{{ "masterPass" | i18n }}</bit-label>
<input
id="login_input_master-password"
bitInput
type="{{ showPassword ? 'text' : 'password' }}"
formControlName="masterPassword"
/>
<button type="button" bitSuffix bitButton (click)="togglePassword()">
<i
aria-hidden="true"
class="bwi bwi-lg bwi-eye"
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
></i>
<div class="tw-mb-3">
<button
bitButton
type="button"
buttonType="primary"
class="tw-w-full"
[disabled]="form.loading"
(click)="validateEmail()"
>
<span> {{ "continue" | i18n }} </span>
</button>
<bit-hint>
<a routerLink="/hint">{{ "getMasterPasswordHint" | i18n }}</a>
</bit-hint>
</bit-form-field>
</div>

<div class="tw-mb-3 tw-flex tw-items-start">
<div class="tw-flex tw-h-6 tw-items-center">
<input
id="login_input_remember-email"
class="tw-w-4 tw-rounded tw-border"
bitInput
type="checkbox"
formControlName="rememberEmail"
/>
</div>
<bit-label class="ml-2">
{{ "rememberEmail" | i18n }}
</bit-label>
</div>

<hr />
<hr />

<p class="tw-m-0 tw-text-sm">
{{ "newAroundHere" | i18n }}
<a routerLink="/register">{{ "createAccount" | i18n }}</a>
</p>
</ng-container>
</div>
</div>
</div>
</form>

<ng-template [formGroup]="formGroup" #loginPage>
<div class="tw-mb-3">
<bit-form-field>
<bit-label>{{ "masterPass" | i18n }}</bit-label>
<input
id="login_input_master-password"
bitInput
type="{{ showPassword ? 'text' : 'password' }}"
formControlName="masterPassword"
/>
<button type="button" bitSuffix bitButton (click)="togglePassword()">
<i
aria-hidden="true"
class="bwi bwi-lg bwi-eye"
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
></i>
</button>
<bit-hint>
<a routerLink="/hint">{{ "getMasterPasswordHint" | i18n }}</a>
</bit-hint>
</bit-form-field>
</div>

<div [hidden]="!showCaptcha()">
<iframe id="hcaptcha_iframe" height="80"></iframe>
</div>
<div [hidden]="!showCaptcha()">
<iframe id="hcaptcha_iframe" height="80"></iframe>
</div>

<div class="tw-mb-3 tw-flex tw-space-x-4">
<button
bitButton
buttonType="primary"
type="submit"
[block]="true"
[loading]="form.loading"
[disabled]="form.loading"
>
<span> <i class="bwi bwi-sign-in"></i> {{ "logIn" | i18n }} </span>
</button>
<div class="tw-mb-3 tw-flex tw-space-x-4">
<button bitButton buttonType="primary" type="submit" [block]="true" [loading]="form.loading">
<span> {{ "loginWithMasterPassword" | i18n }} </span>
</button>
</div>

<a bitButton buttonType="secondary" routerLink="/register" [block]="true">
<i class="bwi bwi-pencil-square"></i>
{{ "createAccount" | i18n }}
</a>
</div>
<div class="tw-mb-3" *ngIf="showLoginWithDevice">
<button
bitButton
type="button"
[block]="true"
buttonType="secondary"
(click)="startPasswordlessLogin()"
>
<span> <i class="bwi bwi-mobile"></i> {{ "loginWithDevice" | i18n }} </span>
</button>
</div>

<div class="tw-mb-3" *ngIf="!selfHosted && showPasswordless">
<button
bitButton
type="button"
buttonType="secondary"
class="tw-w-full"
(click)="startPasswordlessLogin()"
[disabled]="form.loading"
>
<span> <i class="bwi bwi-mobile"></i> {{ "loginWithDevice" | i18n }} </span>
</button>
</div>
<div class="tw-mb-3">
<a routerLink="/sso" bitButton buttonType="secondary" class="tw-w-full">
<i class="bwi bwi-provider tw-mr-2"></i>
{{ "enterpriseSingleSignOn" | i18n }}
</a>
</div>

<div class="tw-mb-3">
<a routerLink="/sso" bitButton buttonType="secondary" class="tw-w-full">
<i class="bwi bwi-provider tw-mr-2"></i>
{{ "enterpriseSingleSignOn" | i18n }}
</a>
</div>
</div>
</div>
<hr />

<div class="tw-m-0 tw-text-sm">
<p class="tw-mb-1">{{ "loggingInAs" | i18n }} {{ loggedEmail }}</p>
<a [routerLink]="[]" (click)="toggleValidateEmail(false)">{{ "notYou" | i18n }}</a>
</div>
</form>
</ng-template>
8 changes: 5 additions & 3 deletions apps/web/src/app/accounts/login/login.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { first } from "rxjs/operators";

import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/components/login.component";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AppIdService } from "@bitwarden/common/abstractions/appId.service";
import { AuthService } from "@bitwarden/common/abstractions/auth.service";
import { CryptoFunctionService } from "@bitwarden/common/abstractions/cryptoFunction.service";
import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service";
Expand Down Expand Up @@ -37,6 +38,8 @@ export class LoginComponent extends BaseLoginComponent {
showPasswordless = false;

constructor(
apiService: ApiService,
appIdService: AppIdService,
authService: AuthService,
router: Router,
i18nService: I18nService,
Expand All @@ -45,7 +48,6 @@ export class LoginComponent extends BaseLoginComponent {
environmentService: EnvironmentService,
passwordGenerationService: PasswordGenerationService,
cryptoFunctionService: CryptoFunctionService,
private apiService: ApiService,
private policyApiService: PolicyApiServiceAbstraction,
private policyService: InternalPolicyService,
logService: LogService,
Expand All @@ -57,6 +59,8 @@ export class LoginComponent extends BaseLoginComponent {
formValidationErrorService: FormValidationErrorsService
) {
super(
apiService,
appIdService,
authService,
router,
platformUtilsService,
Expand Down Expand Up @@ -100,8 +104,6 @@ export class LoginComponent extends BaseLoginComponent {
this.routerService.setPreviousUrl(route.toString());
}
await super.ngOnInit();
const rememberEmail = await this.stateService.getRememberEmail();
this.formGroup.get("rememberEmail")?.setValue(rememberEmail);
});

const invite = await this.stateService.getOrganizationInvitation();
Expand Down
9 changes: 9 additions & 0 deletions apps/web/src/locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,9 @@
"loginWithDeviceEnabledInfo": {
"message": "Log in with device must be enabled in the settings of the Bitwarden mobile app. Need another option?"
},
"loginWithMasterPassword": {
"message": "Log in with master password"
},
"createAccount": {
"message": "Create Account"
},
Expand Down Expand Up @@ -5390,5 +5393,11 @@
},
"numberOfUsers": {
"message": "Number of users"
},
"loggingInAs": {
"message": "Logging in as"
},
"notYou": {
"message": "Not you?"
}
}
Loading

0 comments on commit 9f34158

Please sign in to comment.