diff --git a/apps/browser/src/popup/app.module.ts b/apps/browser/src/popup/app.module.ts index 54443365d1b..e5ef2e7cade 100644 --- a/apps/browser/src/popup/app.module.ts +++ b/apps/browser/src/popup/app.module.ts @@ -87,7 +87,7 @@ import { PrivateModeWarningComponent } from "./components/private-mode-warning.c import { SendListComponent } from "./components/send-list.component"; import { SetPinComponent } from "./components/set-pin.component"; import { UserVerificationComponent } from "./components/user-verification.component"; -import { Fido2Module } from "./fido2/fido2.module"; +import { Fido2Component } from "./fido2/fido2.component"; import { GeneratorComponent } from "./generator/generator.component"; import { PasswordGeneratorHistoryComponent } from "./generator/password-generator-history.component"; import { EffluxDatesComponent as SendEffluxDatesComponent } from "./send/efflux-dates.component"; @@ -193,7 +193,6 @@ registerLocaleData(localeZhTw, "zh-TW"); ReactiveFormsModule, ScrollingModule, ServicesModule, - Fido2Module, ], declarations: [ ActionButtonsComponent, @@ -246,6 +245,7 @@ registerLocaleData(localeZhTw, "zh-TW"); RemovePasswordComponent, VaultSelectComponent, AboutComponent, + Fido2Component, ], providers: [CurrencyPipe, DatePipe], bootstrap: [AppComponent], diff --git a/apps/browser/src/popup/fido2/fido2.component.html b/apps/browser/src/popup/fido2/fido2.component.html index efed0eb967d..e47d4c9aefd 100644 --- a/apps/browser/src/popup/fido2/fido2.component.html +++ b/apps/browser/src/popup/fido2/fido2.component.html @@ -1,16 +1,23 @@ -
- - A site is asking for authentication - - - A site wants to create a new passkey in your vault - - - - -
+ +
+ + A site is asking for authentication + + +
+
+ +
+
+ A site wants to create a new passkey in your vault +
+ + + +
+
diff --git a/apps/browser/src/popup/fido2/fido2.component.ts b/apps/browser/src/popup/fido2/fido2.component.ts index 7695001dbad..3bf346a7cba 100644 --- a/apps/browser/src/popup/fido2/fido2.component.ts +++ b/apps/browser/src/popup/fido2/fido2.component.ts @@ -1,5 +1,10 @@ -import { Component, HostListener } from "@angular/core"; +import { Component, HostListener, OnDestroy, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; +import { Subject, takeUntil } from "rxjs"; + +import { CipherType } from "@bitwarden/common/enums/cipherType"; +import { CipherView } from "@bitwarden/common/models/view/cipher.view"; +import { Fido2KeyView } from "@bitwarden/common/models/view/fido2-key.view"; import { BrowserFido2Message, @@ -11,11 +16,25 @@ import { templateUrl: "fido2.component.html", styleUrls: [], }) -export class Fido2Component { +export class Fido2Component implements OnInit, OnDestroy { + private destroy$ = new Subject(); + + protected data?: BrowserFido2Message; + protected cipher?: CipherView; + constructor(private activatedRoute: ActivatedRoute) {} - get data() { - return this.activatedRoute.snapshot.queryParams as BrowserFido2Message; + ngOnInit(): void { + this.activatedRoute.queryParamMap.pipe(takeUntil(this.destroy$)).subscribe((queryParamMap) => { + this.data = JSON.parse(queryParamMap.get("data")); + + if (this.data?.type === "ConfirmNewCredentialRequest") { + this.cipher = new CipherView(); + this.cipher.name = this.data.name; + this.cipher.type = CipherType.Fido2Key; + this.cipher.fido2Key = new Fido2KeyView(); + } + }); } async accept() { @@ -56,4 +75,9 @@ export class Fido2Component { fallbackRequested: fallback, }); } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } } diff --git a/apps/browser/src/popup/fido2/fido2.module.ts b/apps/browser/src/popup/fido2/fido2.module.ts deleted file mode 100644 index d052dcb0987..00000000000 --- a/apps/browser/src/popup/fido2/fido2.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { CommonModule } from "@angular/common"; -import { NgModule } from "@angular/core"; - -import { Fido2Component } from "./fido2.component"; - -@NgModule({ - imports: [CommonModule], - declarations: [Fido2Component], - exports: [Fido2Component], -}) -export class Fido2Module {} diff --git a/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts b/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts index e8f18923f52..603ed6c4945 100644 --- a/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts +++ b/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts @@ -1,6 +1,9 @@ import { filter, first, lastValueFrom, Subject, takeUntil } from "rxjs"; -import { Fido2UserInterfaceService as Fido2UserInterfaceServiceAbstraction } from "@bitwarden/common/abstractions/fido2/fido2-user-interface.service.abstraction"; +import { + Fido2UserInterfaceService as Fido2UserInterfaceServiceAbstraction, + NewCredentialParams, +} from "@bitwarden/common/abstractions/fido2/fido2-user-interface.service.abstraction"; import { Utils } from "@bitwarden/common/misc/utils"; import { RequestAbortedError } from "../../../../../libs/common/src/abstractions/fido2/fido2.service.abstraction"; @@ -18,6 +21,7 @@ export type BrowserFido2Message = { requestId: string } & ( } | { type: "ConfirmNewCredentialRequest"; + name: string; } | { type: "ConfirmNewCredentialResponse"; @@ -51,7 +55,7 @@ export class BrowserFido2UserInterfaceService implements Fido2UserInterfaceServi async verifyPresence(): Promise { const requestId = Utils.newGuid(); const data: BrowserFido2Message = { type: "VerifyUserRequest", requestId }; - const queryParams = new URLSearchParams(data).toString(); + const queryParams = new URLSearchParams({ data: JSON.stringify(data) }).toString(); this.popupUtilsService.popOut( null, `popup/index.html?uilocation=popout#/fido2?${queryParams}`, @@ -77,10 +81,10 @@ export class BrowserFido2UserInterfaceService implements Fido2UserInterfaceServi return false; } - async confirmNewCredential(): Promise { + async confirmNewCredential({ name }: NewCredentialParams): Promise { const requestId = Utils.newGuid(); - const data: BrowserFido2Message = { type: "ConfirmNewCredentialRequest", requestId }; - const queryParams = new URLSearchParams(data).toString(); + const data: BrowserFido2Message = { type: "ConfirmNewCredentialRequest", requestId, name }; + const queryParams = new URLSearchParams({ data: JSON.stringify(data) }).toString(); this.popupUtilsService.popOut( null, `popup/index.html?uilocation=popout#/fido2?${queryParams}`, diff --git a/libs/common/src/abstractions/fido2/fido2-user-interface.service.abstraction.ts b/libs/common/src/abstractions/fido2/fido2-user-interface.service.abstraction.ts index 6dfed28d5f0..93a87534f07 100644 --- a/libs/common/src/abstractions/fido2/fido2-user-interface.service.abstraction.ts +++ b/libs/common/src/abstractions/fido2/fido2-user-interface.service.abstraction.ts @@ -1,5 +1,9 @@ +export interface NewCredentialParams { + name: string; +} + export abstract class Fido2UserInterfaceService { verifyUser: () => Promise; verifyPresence: () => Promise; - confirmNewCredential: () => Promise; + confirmNewCredential: (params: NewCredentialParams) => Promise; } diff --git a/libs/common/src/services/fido2/fido2.service.ts b/libs/common/src/services/fido2/fido2.service.ts index 098b5659e44..8c38d6be0c4 100644 --- a/libs/common/src/services/fido2/fido2.service.ts +++ b/libs/common/src/services/fido2/fido2.service.ts @@ -42,7 +42,9 @@ export class Fido2Service implements Fido2ServiceAbstraction { async createCredential( params: CredentialRegistrationParams ): Promise { - const presence = await this.fido2UserInterfaceService.confirmNewCredential(); + const presence = await this.fido2UserInterfaceService.confirmNewCredential({ + name: params.origin, + }); // eslint-disable-next-line no-console console.log("Fido2Service.createCredential", params); @@ -123,14 +125,11 @@ export class Fido2Service implements Fido2ServiceAbstraction { credential = await this.getCredentialByRp(params.rpId); } - console.log("Found credential: ", credential); - if (credential === undefined) { throw new NoCredentialFoundError(); } if (credential.origin !== params.origin) { - console.error(`${params.origin} tried to use credential created by ${credential.origin}`); throw new OriginMismatchError(); } @@ -203,8 +202,6 @@ export class Fido2Service implements Fido2ServiceAbstraction { view.fido2Key.rpId = credential.rpId; view.fido2Key.userHandle = Fido2Utils.bufferToString(credential.userHandle); - console.log("saving credential", { view, credential }); - const cipher = await this.cipherService.encrypt(view); await this.cipherService.createWithServer(cipher); @@ -237,22 +234,16 @@ interface AuthDataParams { async function mapCipherViewToBitCredential(cipherView: CipherView): Promise { const keyBuffer = Fido2Utils.stringToBuffer(cipherView.fido2Key.key); - let privateKey; - try { - privateKey = await crypto.subtle.importKey( - "pkcs8", - keyBuffer, - { - name: "ECDSA", - namedCurve: "P-256", - }, - true, - KeyUsages - ); - } catch (err) { - console.log("Error importing key", { err }); - throw err; - } + const privateKey = await crypto.subtle.importKey( + "pkcs8", + keyBuffer, + { + name: "ECDSA", + namedCurve: "P-256", + }, + true, + KeyUsages + ); return { credentialId: new CredentialId(cipherView.id),