mirror of
https://github.com/bitwarden/browser
synced 2026-01-03 17:13:47 +00:00
* feat: add Identity Sso Required Response type as possible response from token endpoint. * feat: consume sso organization identifier to redirect user * feat: add get requiresSso to AuthResult for more ergonomic code. * feat: sso-redirect on sso-required for CLI and Desktop * chore: fixing type errors * test: fix and add tests for new sso method * docs: fix misspelling * fix: get email from AuthResult instead of the FormGroup * fix:claude: when email is not available for SSO login show error toast. * fix:claude: add null safety check
101 lines
3.8 KiB
TypeScript
101 lines
3.8 KiB
TypeScript
// FIXME: Update this file to be type safe and remove this and next line
|
|
// @ts-strict-ignore
|
|
import { Injectable } from "@angular/core";
|
|
import { firstValueFrom } from "rxjs";
|
|
|
|
import { DefaultLoginComponentService, LoginComponentService } from "@bitwarden/auth/angular";
|
|
import { DESKTOP_SSO_CALLBACK, SsoUrlService } from "@bitwarden/auth/common";
|
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
|
import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
|
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
|
import { ToastService } from "@bitwarden/components";
|
|
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
|
|
|
|
@Injectable()
|
|
export class DesktopLoginComponentService
|
|
extends DefaultLoginComponentService
|
|
implements LoginComponentService
|
|
{
|
|
constructor(
|
|
protected cryptoFunctionService: CryptoFunctionService,
|
|
protected environmentService: EnvironmentService,
|
|
protected passwordGenerationService: PasswordGenerationServiceAbstraction,
|
|
protected platformUtilsService: PlatformUtilsService,
|
|
protected ssoLoginService: SsoLoginServiceAbstraction,
|
|
protected i18nService: I18nService,
|
|
protected toastService: ToastService,
|
|
protected ssoUrlService: SsoUrlService,
|
|
) {
|
|
super(
|
|
cryptoFunctionService,
|
|
environmentService,
|
|
passwordGenerationService,
|
|
platformUtilsService,
|
|
ssoLoginService,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* On the desktop, redirecting to the SSO login page is done via a new browser window, opened
|
|
* to the SSO component on the web client.
|
|
* @param email the email of the user trying to log in, used to look up the org SSO identifier
|
|
* @param state the state that will be used to verify the SSO login, which needs to be passed to the IdP
|
|
* @param codeChallenge the challenge that will be verified after the code is returned from the IdP, which needs to be passed to the IdP
|
|
*/
|
|
protected override async redirectToSso(
|
|
email: string,
|
|
state: string,
|
|
codeChallenge: string,
|
|
orgSsoIdentifier?: string,
|
|
): Promise<void> {
|
|
// For platforms that cannot support a protocol-based (e.g. bitwarden://) callback, we use a localhost callback
|
|
// Otherwise, we launch the SSO component in a browser window and wait for the callback
|
|
if (ipc.platform.isAppImage || ipc.platform.isDev) {
|
|
await this.initiateSsoThroughLocalhostCallback(email, state, codeChallenge, orgSsoIdentifier);
|
|
} else {
|
|
const env = await firstValueFrom(this.environmentService.environment$);
|
|
const webVaultUrl = env.getWebVaultUrl();
|
|
|
|
const redirectUri = DESKTOP_SSO_CALLBACK;
|
|
|
|
const ssoWebAppUrl = this.ssoUrlService.buildSsoUrl(
|
|
webVaultUrl,
|
|
this.clientType,
|
|
redirectUri,
|
|
state,
|
|
codeChallenge,
|
|
email,
|
|
orgSsoIdentifier,
|
|
);
|
|
|
|
this.platformUtilsService.launchUri(ssoWebAppUrl);
|
|
}
|
|
}
|
|
|
|
private async initiateSsoThroughLocalhostCallback(
|
|
email: string,
|
|
state: string,
|
|
challenge: string,
|
|
orgSsoIdentifier?: string,
|
|
): Promise<void> {
|
|
try {
|
|
await ipc.platform.localhostCallbackService.openSsoPrompt(
|
|
challenge,
|
|
state,
|
|
email,
|
|
orgSsoIdentifier,
|
|
);
|
|
// FIXME: Remove when updating file. Eslint update
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
} catch (err) {
|
|
this.toastService.showToast({
|
|
variant: "error",
|
|
title: this.i18nService.t("errorOccurred"),
|
|
message: this.i18nService.t("ssoError"),
|
|
});
|
|
}
|
|
}
|
|
}
|