Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PM-8221] Route user to email OTP entry [clients] #12811

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
2877a71
Add new IdentityDeviceVerificationResponse
alec-livefront Dec 27, 2024
b741e45
Respond with IdentityDeviceVerificationResponse
alec-livefront Dec 27, 2024
89cba4f
Add AuthResult and sessionTimeout
alec-livefront Dec 27, 2024
d3d5ee6
Fix imports and integrate IdentityDeviceVerificationResponse
alec-livefront Dec 28, 2024
1d98fa8
Add new device verification component
alec-livefront Dec 28, 2024
0504513
Set up DeviceVerificationRequest
alec-livefront Dec 30, 2024
b377236
Update translations
alec-livefront Jan 2, 2025
1eb8c5a
Handle session timeout and fix resend code
alec-livefront Jan 3, 2025
3db8357
Keep old translation
alec-livefront Jan 7, 2025
4188e4a
Revert "Keep old translation"
alec-livefront Jan 7, 2025
c71bf55
Update AuthResult
alec-livefront Jan 7, 2025
6b637c7
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 7, 2025
03fbd03
Update check for new device verification
alec-livefront Jan 8, 2025
818e0fd
PM-8221 - LoginStrategy - (1) Move new device verification to bottomโ€ฆ
JaredSnider-Bitwarden Jan 8, 2025
5d6fa5c
PM-8221 - (1) Update logInNewDeviceVerification to just accept strinโ€ฆ
JaredSnider-Bitwarden Jan 8, 2025
a5b295a
PM-8221 - Tweak response and request models.
JaredSnider-Bitwarden Jan 8, 2025
6e9337a
PM-8221 - Add todo
JaredSnider-Bitwarden Jan 8, 2025
bb49296
Cleanup and rework logInNewDeviceVerification
alec-livefront Jan 9, 2025
c2d4ee2
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 9, 2025
fc7754b
Fix import and add logging
alec-livefront Jan 9, 2025
5baac33
Add newDeviceVerificationGuard
alec-livefront Jan 9, 2025
3fda156
Cleanup and fix strict type errors
alec-livefront Jan 10, 2025
0c5a559
Cleanup debug
alec-livefront Jan 10, 2025
426a3dd
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 10, 2025
ef37b85
Fix issue logging in and additional strict typing error
alec-livefront Jan 10, 2025
2eb175c
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 10, 2025
d4b6682
clean up code check
alec-livefront Jan 10, 2025
b103f99
Fixing tests
alec-livefront Jan 10, 2025
d90b2bd
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 10, 2025
76588e0
Fix strict typing errors
alec-livefront Jan 11, 2025
25d3c6e
Merge branch 'auth/pm-8221/route-user-to-email-otp-entry-clients' of โ€ฆ
alec-livefront Jan 11, 2025
c9a00c6
match resend margin from Figma
alec-livefront Jan 13, 2025
d1b0175
Use ExtensionAnonLayoutWrapperComponent
alec-livefront Jan 14, 2025
ce10ca3
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 14, 2025
9a8c143
Add toast message on session timeout
alec-livefront Jan 14, 2025
ab91188
Add session timeout toast
alec-livefront Jan 14, 2025
491f29a
Revert "Add toast message on session timeout"
alec-livefront Jan 14, 2025
6bd2558
Do full sync and clear email values
alec-livefront Jan 14, 2025
96a4f03
Update code error handling
alec-livefront Jan 14, 2025
100103d
Add test for logInNewDeviceVerification
alec-livefront Jan 14, 2025
052d9d8
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 14, 2025
84cc367
Add test for logInNewDeviceVerification
alec-livefront Jan 14, 2025
0cae6f4
Add test for processDeviceVerificationResponse
alec-livefront Jan 15, 2025
7a7e917
Merge branch 'auth/pm-8221/route-user-to-email-otp-entry-clients' of โ€ฆ
alec-livefront Jan 15, 2025
0c6233b
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 15, 2025
c4e938e
Add `showBackButton` for device verification screen
alec-livefront Jan 16, 2025
a87d2b6
Update 2fa-timeout to authentication-timeout and replace
alec-livefront Jan 16, 2025
09a4441
Rename newDeviceVerificationGuard to activeAuthGuard
alec-livefront Jan 16, 2025
388d25b
Allow initializeLoginStrategy sources to accept null
alec-livefront Jan 16, 2025
d1a1d42
Update guard tests
alec-livefront Jan 16, 2025
46ed3f6
Make resend code smaller
alec-livefront Jan 16, 2025
7a9e61a
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 16, 2025
001753d
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 16, 2025
f11cf76
Rename TwoFactorTimeout to AuthenticationTimeout
alec-livefront Jan 16, 2025
6350007
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 17, 2025
608dc85
Test cleanup
alec-livefront Jan 17, 2025
5f8c68d
Merge branch 'auth/pm-8221/route-user-to-email-otp-entry-clients' of โ€ฆ
alec-livefront Jan 17, 2025
0299e22
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 17, 2025
6613b2a
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 20, 2025
4204256
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 20, 2025
332a5ad
Rename and move two-factor-auth-expired component to authentication-tโ€ฆ
alec-livefront Jan 22, 2025
447cd75
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 22, 2025
ccac0de
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 22, 2025
9fd82e1
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 22, 2025
1cbb521
Add feature flag and extra guards to device-verification route
alec-livefront Jan 22, 2025
e2e5e2f
Move authResult.requiresDeviceVerification check
alec-livefront Jan 23, 2025
2d965f2
Merge branch 'main' into auth/pm-8221/route-user-to-email-otp-entry-cโ€ฆ
alec-livefront Jan 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/browser/src/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,12 @@
"verifyIdentity": {
"message": "Verify identity"
},
"weDontRecognizeThisDevice": {
"message": "We don't recognize this device. Enter the code sent to your email to verify your identity."
},
"continueLoggingIn": {
"message": "Continue logging in"
},
"yourVaultIsLocked": {
"message": "Your vault is locked. Verify your identity to continue."
},
Expand Down
32 changes: 29 additions & 3 deletions apps/browser/src/popup/app-routing.module.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import { Injectable, NgModule } from "@angular/core";
import { ActivatedRouteSnapshot, RouteReuseStrategy, RouterModule, Routes } from "@angular/router";

import { AuthenticationTimeoutComponent } from "@bitwarden/angular/auth/components/authentication-timeout.component";

Check warning on line 4 in apps/browser/src/popup/app-routing.module.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/popup/app-routing.module.ts#L4

Added line #L4 was not covered by tests
import {
EnvironmentSelectorComponent,
EnvironmentSelectorRouteData,
ExtensionDefaultOverlayPosition,
} from "@bitwarden/angular/auth/components/environment-selector.component";
import { TwoFactorTimeoutComponent } from "@bitwarden/angular/auth/components/two-factor-auth/two-factor-auth-expired.component";
import { unauthUiRefreshRedirect } from "@bitwarden/angular/auth/functions/unauth-ui-refresh-redirect";
import { unauthUiRefreshSwap } from "@bitwarden/angular/auth/functions/unauth-ui-refresh-route-swap";
import {
authGuard,
lockGuard,
activeAuthGuard,
redirectGuard,
tdeDecryptionRequiredGuard,
unauthGuardFn,
} from "@bitwarden/angular/auth/guards";
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";

Check warning on line 20 in apps/browser/src/popup/app-routing.module.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/popup/app-routing.module.ts#L20

Added line #L20 was not covered by tests
import { twofactorRefactorSwap } from "@bitwarden/angular/utils/two-factor-component-refactor-route-swap";
import { NewDeviceVerificationNoticeGuard } from "@bitwarden/angular/vault/guards";
import {
Expand All @@ -39,7 +41,10 @@
DevicesIcon,
SsoComponent,
TwoFactorTimeoutIcon,
NewDeviceVerificationComponent,
DeviceVerificationIcon,
} from "@bitwarden/auth/angular";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";

Check warning on line 47 in apps/browser/src/popup/app-routing.module.ts

View check run for this annotation

Codecov / codecov/patch

apps/browser/src/popup/app-routing.module.ts#L47

Added line #L47 was not covered by tests
import { LockComponent } from "@bitwarden/key-management/angular";
import {
NewDeviceVerificationNoticePageOneComponent,
Expand Down Expand Up @@ -172,12 +177,12 @@
component: ExtensionAnonLayoutWrapperComponent,
children: [
{
path: "2fa-timeout",
path: "authentication-timeout",
canActivate: [unauthGuardFn(unauthRouteOverrides)],
children: [
{
path: "",
component: TwoFactorTimeoutComponent,
component: AuthenticationTimeoutComponent,
},
],
data: {
Expand Down Expand Up @@ -230,6 +235,27 @@
],
},
),
{
path: "device-verification",
component: ExtensionAnonLayoutWrapperComponent,
canActivate: [
canAccessFeature(FeatureFlag.NewDeviceVerification),
unauthGuardFn(),
activeAuthGuard(),
],
children: [{ path: "", component: NewDeviceVerificationComponent }],
data: {
pageIcon: DeviceVerificationIcon,
pageTitle: {
key: "verifyIdentity",
},
pageSubtitle: {
key: "weDontRecognizeThisDevice",
},
showBackButton: true,
elevation: 1,
} satisfies RouteDataProperties & ExtensionAnonLayoutWrapperData,
},
{
path: "set-password",
component: SetPasswordComponent,
Expand Down
30 changes: 27 additions & 3 deletions apps/desktop/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";

import { AuthenticationTimeoutComponent } from "@bitwarden/angular/auth/components/authentication-timeout.component";

Check warning on line 4 in apps/desktop/src/app/app-routing.module.ts

View check run for this annotation

Codecov / codecov/patch

apps/desktop/src/app/app-routing.module.ts#L4

Added line #L4 was not covered by tests
import {
DesktopDefaultOverlayPosition,
EnvironmentSelectorComponent,
} from "@bitwarden/angular/auth/components/environment-selector.component";
import { TwoFactorTimeoutComponent } from "@bitwarden/angular/auth/components/two-factor-auth/two-factor-auth-expired.component";
import { unauthUiRefreshSwap } from "@bitwarden/angular/auth/functions/unauth-ui-refresh-route-swap";
import {
authGuard,
lockGuard,
activeAuthGuard,
redirectGuard,
tdeDecryptionRequiredGuard,
unauthGuardFn,
} from "@bitwarden/angular/auth/guards";
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";

Check warning on line 18 in apps/desktop/src/app/app-routing.module.ts

View check run for this annotation

Codecov / codecov/patch

apps/desktop/src/app/app-routing.module.ts#L18

Added line #L18 was not covered by tests
import { twofactorRefactorSwap } from "@bitwarden/angular/utils/two-factor-component-refactor-route-swap";
import { NewDeviceVerificationNoticeGuard } from "@bitwarden/angular/vault/guards";
import {
Expand All @@ -37,7 +39,10 @@
DevicesIcon,
SsoComponent,
TwoFactorTimeoutIcon,
NewDeviceVerificationComponent,
DeviceVerificationIcon,
} from "@bitwarden/auth/angular";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";

Check warning on line 45 in apps/desktop/src/app/app-routing.module.ts

View check run for this annotation

Codecov / codecov/patch

apps/desktop/src/app/app-routing.module.ts#L45

Added line #L45 was not covered by tests
import { LockComponent } from "@bitwarden/key-management/angular";
import {
NewDeviceVerificationNoticePageOneComponent,
Expand Down Expand Up @@ -97,12 +102,12 @@
},
),
{
path: "2fa-timeout",
path: "authentication-timeout",
component: AnonLayoutWrapperComponent,
children: [
{
path: "",
component: TwoFactorTimeoutComponent,
component: AuthenticationTimeoutComponent,
},
],
data: {
Expand All @@ -112,6 +117,25 @@
},
} satisfies RouteDataProperties & AnonLayoutWrapperData,
},
{
path: "device-verification",
component: AnonLayoutWrapperComponent,
canActivate: [
canAccessFeature(FeatureFlag.NewDeviceVerification),
unauthGuardFn(),
activeAuthGuard(),
],
children: [{ path: "", component: NewDeviceVerificationComponent }],
data: {
pageIcon: DeviceVerificationIcon,
pageTitle: {
key: "verifyIdentity",
},
pageSubtitle: {
key: "weDontRecognizeThisDevice",
},
} satisfies RouteDataProperties & AnonLayoutWrapperData,
},
{ path: "register", component: RegisterComponent },
{
path: "new-device-notice",
Expand Down
9 changes: 9 additions & 0 deletions apps/desktop/src/locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,15 @@
"message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.",
"description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated."
},
"verifyIdentity": {
"message": "Verify your Identity"
},
"weDontRecognizeThisDevice": {
"message": "We don't recognize this device. Enter the code sent to your email to verify your identity."
},
"continueLoggingIn": {
"message": "Continue logging in"
},
"webAuthnTitle": {
"message": "FIDO2 WebAuthn"
},
Expand Down
34 changes: 31 additions & 3 deletions apps/web/src/app/oss-routing.module.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { NgModule } from "@angular/core";
import { Route, RouterModule, Routes } from "@angular/router";

import { TwoFactorTimeoutComponent } from "@bitwarden/angular/auth/components/two-factor-auth/two-factor-auth-expired.component";
import { AuthenticationTimeoutComponent } from "@bitwarden/angular/auth/components/authentication-timeout.component";

Check warning on line 4 in apps/web/src/app/oss-routing.module.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/oss-routing.module.ts#L4

Added line #L4 was not covered by tests
import { unauthUiRefreshSwap } from "@bitwarden/angular/auth/functions/unauth-ui-refresh-route-swap";
import {
authGuard,
lockGuard,
redirectGuard,
tdeDecryptionRequiredGuard,
unauthGuardFn,
activeAuthGuard,
} from "@bitwarden/angular/auth/guards";
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";

Check warning on line 14 in apps/web/src/app/oss-routing.module.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/oss-routing.module.ts#L14

Added line #L14 was not covered by tests
import { generatorSwap } from "@bitwarden/angular/tools/generator/generator-swap";
import { twofactorRefactorSwap } from "@bitwarden/angular/utils/two-factor-component-refactor-route-swap";
import { NewDeviceVerificationNoticeGuard } from "@bitwarden/angular/vault/guards";
Expand Down Expand Up @@ -37,7 +39,10 @@
SsoComponent,
VaultIcon,
LoginDecryptionOptionsComponent,
NewDeviceVerificationComponent,
DeviceVerificationIcon,
} from "@bitwarden/auth/angular";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";

Check warning on line 45 in apps/web/src/app/oss-routing.module.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/oss-routing.module.ts#L45

Added line #L45 was not covered by tests
import { LockComponent } from "@bitwarden/key-management/angular";
import {
NewDeviceVerificationNoticePageOneComponent,
Expand Down Expand Up @@ -538,12 +543,12 @@
} satisfies RouteDataProperties & AnonLayoutWrapperData,
},
{
path: "2fa-timeout",
path: "authentication-timeout",
canActivate: [unauthGuardFn()],
children: [
{
path: "",
component: TwoFactorTimeoutComponent,
component: AuthenticationTimeoutComponent,
},
{
path: "",
Expand Down Expand Up @@ -580,6 +585,29 @@
titleId: "recoverAccountTwoStep",
} satisfies RouteDataProperties & AnonLayoutWrapperData,
},
{
path: "device-verification",
canActivate: [
canAccessFeature(FeatureFlag.NewDeviceVerification),
unauthGuardFn(),
activeAuthGuard(),
],
children: [
{
path: "",
component: NewDeviceVerificationComponent,
},
],
data: {
pageIcon: DeviceVerificationIcon,
pageTitle: {
key: "verifyIdentity",
},
pageSubtitle: {
key: "weDontRecognizeThisDevice",
},
} satisfies RouteDataProperties & AnonLayoutWrapperData,
},
{
path: "accept-emergency",
canActivate: [deepLinkGuard()],
Expand Down
6 changes: 6 additions & 0 deletions apps/web/src/locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,12 @@
"verifyIdentity": {
"message": "Verify your Identity"
},
"weDontRecognizeThisDevice": {
"message": "We don't recognize this device. Enter the code sent to your email to verify your identity."
},
"continueLoggingIn": {
"message": "Continue logging in"
},
"whatIsADevice": {
"message": "What is a device?"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* It provides a button to navigate to the login page.
*/
@Component({
selector: "app-two-factor-expired",
selector: "app-authentication-timeout",
standalone: true,
imports: [CommonModule, JslibModule, ButtonModule, RouterModule],
template: `
Expand All @@ -22,4 +22,4 @@
</a>
`,
})
export class TwoFactorTimeoutComponent {}
export class AuthenticationTimeoutComponent {}

Check warning on line 25 in libs/angular/src/auth/components/authentication-timeout.component.ts

View check run for this annotation

Codecov / codecov/patch

libs/angular/src/auth/components/authentication-timeout.component.ts#L25

Added line #L25 was not covered by tests
14 changes: 8 additions & 6 deletions libs/angular/src/auth/components/two-factor.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@ describe("TwoFactorComponent", () => {
};

let selectedUserDecryptionOptions: BehaviorSubject<UserDecryptionOptions>;
let twoFactorTimeoutSubject: BehaviorSubject<boolean>;
let authenticationSessionTimeoutSubject: BehaviorSubject<boolean>;

beforeEach(() => {
twoFactorTimeoutSubject = new BehaviorSubject<boolean>(false);
authenticationSessionTimeoutSubject = new BehaviorSubject<boolean>(false);
mockLoginStrategyService = mock<LoginStrategyServiceAbstraction>();
mockLoginStrategyService.twoFactorTimeout$ = twoFactorTimeoutSubject;
mockLoginStrategyService.authenticationSessionTimeout$ = authenticationSessionTimeoutSubject;
mockRouter = mock<Router>();
mockI18nService = mock<I18nService>();
mockApiService = mock<ApiService>();
Expand Down Expand Up @@ -153,7 +153,9 @@ describe("TwoFactorComponent", () => {
}),
};

selectedUserDecryptionOptions = new BehaviorSubject<UserDecryptionOptions>(null);
selectedUserDecryptionOptions = new BehaviorSubject<UserDecryptionOptions>(
mockUserDecryptionOpts.withMasterPassword,
);
mockUserDecryptionOptionsService.userDecryptionOptions$ = selectedUserDecryptionOptions;

TestBed.configureTestingModule({
Expand Down Expand Up @@ -497,8 +499,8 @@ describe("TwoFactorComponent", () => {
});

it("navigates to the timeout route when timeout expires", async () => {
twoFactorTimeoutSubject.next(true);
authenticationSessionTimeoutSubject.next(true);

expect(mockRouter.navigate).toHaveBeenCalledWith(["2fa-timeout"]);
expect(mockRouter.navigate).toHaveBeenCalledWith(["authentication-timeout"]);
});
});
6 changes: 3 additions & 3 deletions libs/angular/src/auth/components/two-factor.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
protected changePasswordRoute = "set-password";
protected forcePasswordResetRoute = "update-temp-password";
protected successRoute = "vault";
protected twoFactorTimeoutRoute = "2fa-timeout";
protected twoFactorTimeoutRoute = "authentication-timeout";

get isDuoProvider(): boolean {
return (
Expand Down Expand Up @@ -104,8 +104,8 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
super(environmentService, i18nService, platformUtilsService, toastService);
this.webAuthnSupported = this.platformUtilsService.supportsWebAuthn(win);

// Add subscription to twoFactorTimeout$ and navigate to twoFactorTimeoutRoute if expired
this.loginStrategyService.twoFactorTimeout$
// Add subscription to authenticationSessionTimeout$ and navigate to twoFactorTimeoutRoute if expired
this.loginStrategyService.authenticationSessionTimeout$
.pipe(takeUntilDestroyed())
.subscribe(async (expired) => {
if (!expired) {
Expand Down
Loading
Loading