From 4598e8edc194bdfd9e582490014ff8c76be2d6a3 Mon Sep 17 00:00:00 2001 From: Jared Snider Date: Tue, 23 Dec 2025 17:50:53 -0500 Subject: [PATCH] PM-14922 - WIP SDK password login demo --- .../login/web-login-component.service.ts | 44 ++++++++++++++++++- apps/web/src/app/core/core.module.ts | 2 + .../angular/login/login-component.service.ts | 18 ++++++++ .../auth/src/angular/login/login.component.ts | 32 ++++++++------ 4 files changed, 81 insertions(+), 15 deletions(-) diff --git a/apps/web/src/app/auth/core/services/login/web-login-component.service.ts b/apps/web/src/app/auth/core/services/login/web-login-component.service.ts index 8c1bc4bd080..d296345b10f 100644 --- a/apps/web/src/app/auth/core/services/login/web-login-component.service.ts +++ b/apps/web/src/app/auth/core/services/login/web-login-component.service.ts @@ -2,6 +2,7 @@ // @ts-strict-ignore import { Injectable } from "@angular/core"; import { Router } from "@angular/router"; +import { firstValueFrom } from "rxjs"; import { DefaultLoginComponentService, @@ -16,10 +17,21 @@ import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/ import { OrganizationInviteService } from "@bitwarden/common/auth/services/organization-invite/organization-invite.service"; import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; -import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; +import { + Environment, + EnvironmentService, +} from "@bitwarden/common/platform/abstractions/environment.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { SdkService, toSdkDevice } from "@bitwarden/common/platform/abstractions/sdk/sdk.service"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; +import { + ClientSettings, + PasswordManagerClient, + PasswordPreloginResponse, + PasswordLoginRequest, + LoginResponse, +} from "@bitwarden/sdk-internal"; import { RouterService } from "../../../../core/router.service"; @@ -42,6 +54,7 @@ export class WebLoginComponentService private router: Router, private accountService: AccountService, private configService: ConfigService, + private sdkService: SdkService, ) { super( cryptoFunctionService, @@ -125,4 +138,33 @@ export class WebLoginComponentService }; } } + + async sdkPasswordPrelogin(email: string): Promise { + const anonSdkClient: PasswordManagerClient = await firstValueFrom(this.sdkService.client$); + + const env = await firstValueFrom(this.environmentService.environment$); + + const settings = this.toSettings(env); + + return await anonSdkClient.auth().login(settings).get_password_prelogin(email); + } + + async sdkLoginWithPassword(request: PasswordLoginRequest): Promise { + const anonSdkClient: PasswordManagerClient = await firstValueFrom(this.sdkService.client$); + + const env = await firstValueFrom(this.environmentService.environment$); + + const settings = this.toSettings(env); + + return await anonSdkClient.auth().login(settings).login_via_password(request); + } + + private toSettings(env: Environment): ClientSettings { + return { + apiUrl: env.getApiUrl(), + identityUrl: env.getIdentityUrl(), + deviceType: toSdkDevice(this.platformUtilsService.getDevice()), + userAgent: navigator.userAgent, + }; + } } diff --git a/apps/web/src/app/core/core.module.ts b/apps/web/src/app/core/core.module.ts index bd557dc5947..d5effecf08e 100644 --- a/apps/web/src/app/core/core.module.ts +++ b/apps/web/src/app/core/core.module.ts @@ -88,6 +88,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { SdkClientFactory } from "@bitwarden/common/platform/abstractions/sdk/sdk-client-factory"; import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service"; +import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service"; import { AbstractStorageService } from "@bitwarden/common/platform/abstractions/storage.service"; import { SystemService } from "@bitwarden/common/platform/abstractions/system.service"; import { IpcService } from "@bitwarden/common/platform/ipc"; @@ -340,6 +341,7 @@ const safeProviders: SafeProvider[] = [ Router, AccountService, ConfigService, + SdkService, ], }), safeProvider({ diff --git a/libs/auth/src/angular/login/login-component.service.ts b/libs/auth/src/angular/login/login-component.service.ts index b7c2b16ce24..a6e937baab6 100644 --- a/libs/auth/src/angular/login/login-component.service.ts +++ b/libs/auth/src/angular/login/login-component.service.ts @@ -2,6 +2,11 @@ // @ts-strict-ignore import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options"; import { Policy } from "@bitwarden/common/admin-console/models/domain/policy"; +import { + PasswordLoginRequest, + PasswordPreloginResponse, + LoginResponse, +} from "@bitwarden/sdk-internal"; export interface PasswordPolicies { policies: Policy[]; @@ -47,4 +52,17 @@ export abstract class LoginComponentService { * Shows the back button. */ showBackButton: (showBackButton: boolean) => void; + + /** + * Retrieves the password prelogin data required for authentication. + * This includes the user's KDF configuration needed to properly derive the master key. + * - Demo method for testing SDK login functionality + */ + sdkPasswordPrelogin?: (email: string) => Promise; + + /** + * Authenticates a user via email and master password using the SDK. + * - Demo method for testing SDK login functionality + */ + sdkLoginWithPassword?: (request: PasswordLoginRequest) => Promise; } diff --git a/libs/auth/src/angular/login/login.component.ts b/libs/auth/src/angular/login/login.component.ts index 8e688f3f830..ceb69636ca1 100644 --- a/libs/auth/src/angular/login/login.component.ts +++ b/libs/auth/src/angular/login/login.component.ts @@ -29,7 +29,7 @@ import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstraction import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result"; import { ClientType, HttpStatusCode } from "@bitwarden/common/enums"; -import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; +// import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; @@ -668,20 +668,24 @@ export class LoginComponent implements OnInit, OnDestroy { } private async makePasswordPreloginCall() { - // Prefetch prelogin KDF config when enabled - try { - const flagEnabled = await this.configService.getFeatureFlag( - FeatureFlag.PM23801_PrefetchPasswordPrelogin, - ); - if (flagEnabled) { - const email = this.formGroup.value.email; - if (email) { - void this.loginStrategyService.getPasswordPrelogin(email); - } - } - } catch (error) { - this.logService.error("Failed to prefetch prelogin data.", error); + if (this.formGroup.value.email) { + await this.loginComponentService.sdkPasswordPrelogin?.(this.formGroup.value.email); } + + // // Prefetch prelogin KDF config when enabled + // try { + // const flagEnabled = await this.configService.getFeatureFlag( + // FeatureFlag.PM23801_PrefetchPasswordPrelogin, + // ); + // if (flagEnabled) { + // const email = this.formGroup.value.email; + // if (email) { + // void this.loginStrategyService.getPasswordPrelogin(email); + // } + // } + // } catch (error) { + // this.logService.error("Failed to prefetch prelogin data.", error); + // } } /**