diff --git a/libs/auth/src/angular/login/login.component.html b/libs/auth/src/angular/login/login.component.html index 364e200e65..75e8f1de86 100644 --- a/libs/auth/src/angular/login/login.component.html +++ b/libs/auth/src/angular/login/login.component.html @@ -147,32 +147,13 @@ {{ "continue" | i18n }} - - - + - - + + diff --git a/libs/auth/src/angular/login/login.component.ts b/libs/auth/src/angular/login/login.component.ts index eb0e559c00..01f9c23855 100644 --- a/libs/auth/src/angular/login/login.component.ts +++ b/libs/auth/src/angular/login/login.component.ts @@ -16,12 +16,14 @@ import { PolicyData } from "@bitwarden/common/admin-console/models/data/policy.d import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options"; import { Policy } from "@bitwarden/common/admin-console/models/domain/policy"; import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction"; +import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction"; import { CaptchaIFrame } from "@bitwarden/common/auth/captcha-iframe"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result"; import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason"; import { ClientType } from "@bitwarden/common/enums"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; +import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; @@ -38,6 +40,7 @@ import { IconButtonModule, ToastService, } from "@bitwarden/components"; +import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; import { AnonLayoutWrapperDataService } from "../anon-layout/anon-layout-wrapper-data.service"; import { WaveIcon } from "../icons"; @@ -117,6 +120,7 @@ export class LoginComponent implements OnInit, OnDestroy { private anonLayoutWrapperDataService: AnonLayoutWrapperDataService, private appIdService: AppIdService, private broadcasterService: BroadcasterService, + private cryptoFunctionService: CryptoFunctionService, private devicesApiService: DevicesApiServiceAbstraction, private environmentService: EnvironmentService, private formBuilder: FormBuilder, @@ -126,11 +130,13 @@ export class LoginComponent implements OnInit, OnDestroy { private loginStrategyService: LoginStrategyServiceAbstraction, private messagingService: MessagingService, private ngZone: NgZone, + private passwordGenerationService: PasswordGenerationServiceAbstraction, private passwordStrengthService: PasswordStrengthServiceAbstraction, private platformUtilsService: PlatformUtilsService, private policyService: InternalPolicyService, private registerRouteService: RegisterRouteService, private router: Router, + private ssoLoginService: SsoLoginServiceAbstraction, private syncService: SyncService, private toastService: ToastService, ) { @@ -279,6 +285,53 @@ export class LoginComponent implements OnInit, OnDestroy { } } + protected async launchSsoBrowser() { + // Save off email for SSO + await this.ssoLoginService.setSsoEmail(this.formGroup.value.email); + + // Generate necessary sso params + const passwordOptions: any = { + type: "password", + length: 64, + uppercase: true, + lowercase: true, + numbers: true, + special: false, + }; + + const state = + (await this.passwordGenerationService.generatePassword(passwordOptions)) + + ":clientId=browser"; + const codeVerifier = await this.passwordGenerationService.generatePassword(passwordOptions); + const codeVerifierHash = await this.cryptoFunctionService.hash(codeVerifier, "sha256"); + const codeChallenge = Utils.fromBufferToUrlB64(codeVerifierHash); + + await this.ssoLoginService.setCodeVerifier(codeVerifier); + await this.ssoLoginService.setSsoState(state); + + const env = await firstValueFrom(this.environmentService.environment$); + let url = env.getWebVaultUrl(); + if (url == null) { + url = "https://vault.bitwarden.com"; + } + + const redirectUri = url + "/sso-connector.html"; + + // Launch browser + this.platformUtilsService.launchUri( + url + + "/#/sso?clientId=browser" + + "&redirectUri=" + + encodeURIComponent(redirectUri) + + "&state=" + + state + + "&codeChallenge=" + + codeChallenge + + "&email=" + + encodeURIComponent(this.formGroup.controls.email.value), + ); + } + protected async goAfterLogIn(userId: UserId): Promise { const masterPassword = this.formGroup.value.masterPassword;