mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 16:23:44 +00:00
move extension launchSsoBrowserWindow() to extension service
This commit is contained in:
@@ -1,9 +1,73 @@
|
|||||||
|
import { inject } from "@angular/core";
|
||||||
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { DefaultLoginService, LoginService } from "@bitwarden/auth/angular";
|
import { DefaultLoginService, LoginService } from "@bitwarden/auth/angular";
|
||||||
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||||
|
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||||
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
|
||||||
|
|
||||||
import { flagEnabled } from "../../../platform/flags"; // TODO-rr-bw: do I need a client specific `flagEnabled()` fn?
|
import { flagEnabled } from "../../../platform/flags"; // TODO-rr-bw: do I need a client specific `flagEnabled()` fn?
|
||||||
|
|
||||||
export class ExtensionLoginService extends DefaultLoginService implements LoginService {
|
export class ExtensionLoginService extends DefaultLoginService implements LoginService {
|
||||||
|
ssoLoginService = inject(SsoLoginServiceAbstraction);
|
||||||
|
passwordGenerationService = inject(PasswordGenerationServiceAbstraction);
|
||||||
|
cryptoFunctionService = inject(CryptoFunctionService);
|
||||||
|
environmentService = inject(EnvironmentService);
|
||||||
|
platformUtilsService = inject(PlatformUtilsService);
|
||||||
|
|
||||||
getShowPasswordlessFlag(): boolean {
|
getShowPasswordlessFlag(): boolean {
|
||||||
return flagEnabled("showPasswordless");
|
return flagEnabled("showPasswordless");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async launchSsoBrowserWindow(email: string): Promise<void | null> {
|
||||||
|
// Save off email for SSO
|
||||||
|
await this.ssoLoginService.setSsoEmail(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(email),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
CLIENT_TYPE,
|
CLIENT_TYPE,
|
||||||
} from "@bitwarden/angular/services/injection-tokens";
|
} from "@bitwarden/angular/services/injection-tokens";
|
||||||
import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module";
|
import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module";
|
||||||
import { AnonLayoutWrapperDataService } from "@bitwarden/auth/angular";
|
import { AnonLayoutWrapperDataService, LoginService } from "@bitwarden/auth/angular";
|
||||||
import { PinServiceAbstraction } from "@bitwarden/auth/common";
|
import { PinServiceAbstraction } from "@bitwarden/auth/common";
|
||||||
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
|
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
|
||||||
@@ -92,6 +92,7 @@ import { DialogService, ToastService } from "@bitwarden/components";
|
|||||||
import { PasswordRepromptService } from "@bitwarden/vault";
|
import { PasswordRepromptService } from "@bitwarden/vault";
|
||||||
|
|
||||||
import { ExtensionAnonLayoutWrapperDataService } from "../../auth/popup/extension-anon-layout-wrapper/extension-anon-layout-wrapper-data.service";
|
import { ExtensionAnonLayoutWrapperDataService } from "../../auth/popup/extension-anon-layout-wrapper/extension-anon-layout-wrapper-data.service";
|
||||||
|
import { ExtensionLoginService } from "../../auth/popup/login/extension-login.service";
|
||||||
import { AutofillService as AutofillServiceAbstraction } from "../../autofill/services/abstractions/autofill.service";
|
import { AutofillService as AutofillServiceAbstraction } from "../../autofill/services/abstractions/autofill.service";
|
||||||
import AutofillService from "../../autofill/services/autofill.service";
|
import AutofillService from "../../autofill/services/autofill.service";
|
||||||
import MainBackground from "../../background/main.background";
|
import MainBackground from "../../background/main.background";
|
||||||
@@ -560,6 +561,11 @@ const safeProviders: SafeProvider[] = [
|
|||||||
useClass: ExtensionAnonLayoutWrapperDataService,
|
useClass: ExtensionAnonLayoutWrapperDataService,
|
||||||
deps: [],
|
deps: [],
|
||||||
}),
|
}),
|
||||||
|
safeProvider({
|
||||||
|
provide: LoginService,
|
||||||
|
useClass: ExtensionLoginService,
|
||||||
|
deps: [I18nServiceAbstraction, ToastService],
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ export class DefaultLoginService implements LoginService {
|
|||||||
protected toastService: ToastService,
|
protected toastService: ToastService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
async launchSsoBrowserWindow(email: string): Promise<void | null> {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
getShowPasswordlessFlag(): boolean {
|
getShowPasswordlessFlag(): boolean {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,7 +150,13 @@
|
|||||||
<!-- TODO-rr-bw: Figma shows no Login with Passkey option on browser. Is that intentional? -->
|
<!-- TODO-rr-bw: Figma shows no Login with Passkey option on browser. Is that intentional? -->
|
||||||
|
|
||||||
<!-- Button to Login with SSO -->
|
<!-- Button to Login with SSO -->
|
||||||
<button type="button" bitButton block buttonType="secondary" (click)="launchSsoBrowser()">
|
<button
|
||||||
|
type="button"
|
||||||
|
bitButton
|
||||||
|
block
|
||||||
|
buttonType="secondary"
|
||||||
|
(click)="launchSsoBrowserWindow()"
|
||||||
|
>
|
||||||
<i class="bwi bwi-provider tw-mr-1"></i>
|
<i class="bwi bwi-provider tw-mr-1"></i>
|
||||||
{{ "useSingleSignOn" | i18n }}
|
{{ "useSingleSignOn" | i18n }}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -16,14 +16,12 @@ 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 { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
|
||||||
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
||||||
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
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 { CaptchaIFrame } from "@bitwarden/common/auth/captcha-iframe";
|
||||||
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
||||||
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
||||||
import { ClientType } from "@bitwarden/common/enums";
|
import { ClientType } from "@bitwarden/common/enums";
|
||||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.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 { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
@@ -40,7 +38,6 @@ import {
|
|||||||
IconButtonModule,
|
IconButtonModule,
|
||||||
ToastService,
|
ToastService,
|
||||||
} from "@bitwarden/components";
|
} from "@bitwarden/components";
|
||||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
|
|
||||||
|
|
||||||
import { AnonLayoutWrapperDataService } from "../anon-layout/anon-layout-wrapper-data.service";
|
import { AnonLayoutWrapperDataService } from "../anon-layout/anon-layout-wrapper-data.service";
|
||||||
import { WaveIcon } from "../icons";
|
import { WaveIcon } from "../icons";
|
||||||
@@ -120,7 +117,6 @@ export class LoginComponent implements OnInit, OnDestroy {
|
|||||||
private anonLayoutWrapperDataService: AnonLayoutWrapperDataService,
|
private anonLayoutWrapperDataService: AnonLayoutWrapperDataService,
|
||||||
private appIdService: AppIdService,
|
private appIdService: AppIdService,
|
||||||
private broadcasterService: BroadcasterService,
|
private broadcasterService: BroadcasterService,
|
||||||
private cryptoFunctionService: CryptoFunctionService,
|
|
||||||
private devicesApiService: DevicesApiServiceAbstraction,
|
private devicesApiService: DevicesApiServiceAbstraction,
|
||||||
private environmentService: EnvironmentService,
|
private environmentService: EnvironmentService,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
@@ -130,13 +126,11 @@ export class LoginComponent implements OnInit, OnDestroy {
|
|||||||
private loginStrategyService: LoginStrategyServiceAbstraction,
|
private loginStrategyService: LoginStrategyServiceAbstraction,
|
||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
private ngZone: NgZone,
|
private ngZone: NgZone,
|
||||||
private passwordGenerationService: PasswordGenerationServiceAbstraction,
|
|
||||||
private passwordStrengthService: PasswordStrengthServiceAbstraction,
|
private passwordStrengthService: PasswordStrengthServiceAbstraction,
|
||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
private policyService: InternalPolicyService,
|
private policyService: InternalPolicyService,
|
||||||
private registerRouteService: RegisterRouteService,
|
private registerRouteService: RegisterRouteService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private ssoLoginService: SsoLoginServiceAbstraction,
|
|
||||||
private syncService: SyncService,
|
private syncService: SyncService,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
) {
|
) {
|
||||||
@@ -285,51 +279,8 @@ export class LoginComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async launchSsoBrowser() {
|
protected async launchSsoBrowserWindow(): Promise<void> {
|
||||||
// Save off email for SSO
|
await this.loginService.launchSsoBrowserWindow(this.loggedEmail);
|
||||||
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<void> {
|
protected async goAfterLogIn(userId: UserId): Promise<void> {
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ export interface PasswordPolicies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export abstract class LoginService {
|
export abstract class LoginService {
|
||||||
// Web specific
|
// Browser/Desktop
|
||||||
|
launchSsoBrowserWindow: (email: string) => Promise<void>;
|
||||||
|
|
||||||
|
// Web
|
||||||
getShowPasswordlessFlag: () => boolean;
|
getShowPasswordlessFlag: () => boolean;
|
||||||
getOrgPolicies: () => Promise<PasswordPolicies | null>;
|
getOrgPolicies: () => Promise<PasswordPolicies | null>;
|
||||||
setPreviousUrl: (route: UrlTree) => void | null;
|
setPreviousUrl: (route: UrlTree) => void | null;
|
||||||
|
|||||||
Reference in New Issue
Block a user