1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 07:43:35 +00:00

[PM-5364] Create SSO Login Service and add state ownership (#7485)

* create sso service

* rename sso service to sso-login service

* rename service

* add references to sso login service and update state calls

* fix browser

* fix desktop

* return promises

* remove sso state from account and global objects

* more descriptive org sso identifier method names

* fix sso tests

* fix tests
This commit is contained in:
Jake Fink
2024-02-08 12:44:35 -05:00
committed by GitHub
parent c2ed6383c6
commit 304c492f24
29 changed files with 259 additions and 177 deletions

View File

@@ -0,0 +1,28 @@
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { SsoLoginService } from "@bitwarden/common/auth/services/sso-login.service";
import {
CachedServices,
factory,
FactoryOptions,
} from "../../../platform/background/service-factories/factory-options";
import {
stateProviderFactory,
StateProviderInitOptions,
} from "../../../platform/background/service-factories/state-provider.factory";
type SsoLoginServiceFactoryOptions = FactoryOptions;
export type SsoLoginServiceInitOptions = SsoLoginServiceFactoryOptions & StateProviderInitOptions;
export function ssoLoginServiceFactory(
cache: { ssoLoginService?: SsoLoginServiceAbstraction } & CachedServices,
opts: SsoLoginServiceInitOptions,
): Promise<SsoLoginServiceAbstraction> {
return factory(
cache,
"ssoLoginService",
opts,
async () => new SsoLoginService(await stateProviderFactory(cache, opts)),
);
}

View File

@@ -7,6 +7,7 @@ import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstrac
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
@@ -45,6 +46,7 @@ export class LoginComponent extends BaseLoginComponent {
formValidationErrorService: FormValidationErrorsService,
route: ActivatedRoute,
loginService: LoginService,
ssoLoginService: SsoLoginServiceAbstraction,
webAuthnLoginService: WebAuthnLoginServiceAbstraction,
) {
super(
@@ -64,6 +66,7 @@ export class LoginComponent extends BaseLoginComponent {
formValidationErrorService,
route,
loginService,
ssoLoginService,
webAuthnLoginService,
);
super.onSuccessfulLogin = async () => {
@@ -106,8 +109,8 @@ export class LoginComponent extends BaseLoginComponent {
const codeVerifierHash = await this.cryptoFunctionService.hash(codeVerifier, "sha256");
const codeChallenge = Utils.fromBufferToUrlB64(codeVerifierHash);
await this.stateService.setSsoCodeVerifier(codeVerifier);
await this.stateService.setSsoState(state);
await this.ssoLoginService.setCodeVerifier(codeVerifier);
await this.ssoLoginService.setSsoState(state);
let url = this.environmentService.getWebVaultUrl();
if (url == null) {

View File

@@ -7,6 +7,7 @@ import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-conso
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@@ -36,6 +37,7 @@ export class SetPasswordComponent extends BaseSetPasswordComponent {
route: ActivatedRoute,
organizationApiService: OrganizationApiServiceAbstraction,
organizationUserService: OrganizationUserService,
ssoLoginService: SsoLoginServiceAbstraction,
dialogService: DialogService,
) {
super(
@@ -53,6 +55,7 @@ export class SetPasswordComponent extends BaseSetPasswordComponent {
stateService,
organizationApiService,
organizationUserService,
ssoLoginService,
dialogService,
);
}

View File

@@ -6,6 +6,7 @@ import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
@@ -25,6 +26,7 @@ import { BrowserApi } from "../../platform/browser/browser-api";
})
export class SsoComponent extends BaseSsoComponent {
constructor(
ssoLoginService: SsoLoginServiceAbstraction,
loginStrategyService: LoginStrategyServiceAbstraction,
router: Router,
i18nService: I18nService,
@@ -42,6 +44,7 @@ export class SsoComponent extends BaseSsoComponent {
@Inject(WINDOW) private win: Window,
) {
super(
ssoLoginService,
loginStrategyService,
router,
i18nService,

View File

@@ -8,6 +8,7 @@ import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
@@ -55,6 +56,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
appIdService: AppIdService,
loginService: LoginService,
configService: ConfigServiceAbstraction,
ssoLoginService: SsoLoginServiceAbstraction,
private dialogService: DialogService,
@Inject(WINDOW) protected win: Window,
private browserMessagingApi: ZonedMessageListenerService,
@@ -73,6 +75,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
twoFactorService,
appIdService,
loginService,
ssoLoginService,
configService,
);
super.onSuccessfulLogin = async () => {

View File

@@ -10,6 +10,7 @@ import { ModalService } from "@bitwarden/angular/services/modal.service";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
@@ -73,6 +74,7 @@ export class LoginComponent extends BaseLoginComponent implements OnDestroy {
formValidationErrorService: FormValidationErrorsService,
route: ActivatedRoute,
loginService: LoginService,
ssoLoginService: SsoLoginServiceAbstraction,
webAuthnLoginService: WebAuthnLoginServiceAbstraction,
) {
super(
@@ -92,6 +94,7 @@ export class LoginComponent extends BaseLoginComponent implements OnDestroy {
formValidationErrorService,
route,
loginService,
ssoLoginService,
webAuthnLoginService,
);
super.onSuccessfulLogin = () => {

View File

@@ -7,6 +7,7 @@ import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-conso
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@@ -43,6 +44,7 @@ export class SetPasswordComponent extends BaseSetPasswordComponent implements On
stateService: StateService,
organizationApiService: OrganizationApiServiceAbstraction,
organizationUserService: OrganizationUserService,
ssoLoginService: SsoLoginServiceAbstraction,
dialogService: DialogService,
) {
super(
@@ -60,6 +62,7 @@ export class SetPasswordComponent extends BaseSetPasswordComponent implements On
stateService,
organizationApiService,
organizationUserService,
ssoLoginService,
dialogService,
);
}

View File

@@ -4,6 +4,7 @@ import { ActivatedRoute, Router } from "@angular/router";
import { SsoComponent as BaseSsoComponent } from "@bitwarden/angular/auth/components/sso.component";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
@@ -20,6 +21,7 @@ import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.serv
})
export class SsoComponent extends BaseSsoComponent {
constructor(
ssoLoginService: SsoLoginServiceAbstraction,
loginStrategyService: LoginStrategyServiceAbstraction,
router: Router,
i18nService: I18nService,
@@ -35,6 +37,7 @@ export class SsoComponent extends BaseSsoComponent {
configService: ConfigServiceAbstraction,
) {
super(
ssoLoginService,
loginStrategyService,
router,
i18nService,

View File

@@ -7,6 +7,7 @@ import { ModalService } from "@bitwarden/angular/services/modal.service";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
@@ -46,6 +47,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
twoFactorService: TwoFactorService,
appIdService: AppIdService,
loginService: LoginService,
ssoLoginService: SsoLoginServiceAbstraction,
configService: ConfigServiceAbstraction,
@Inject(WINDOW) protected win: Window,
) {
@@ -63,6 +65,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
twoFactorService,
appIdService,
loginService,
ssoLoginService,
configService,
);
super.onSuccessfulLogin = async () => {

View File

@@ -15,6 +15,7 @@ import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
import { PolicyResponse } from "@bitwarden/common/admin-console/models/response/policy.response";
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
import { ListResponse } from "@bitwarden/common/models/response/list.response";
@@ -64,6 +65,7 @@ export class LoginComponent extends BaseLoginComponent implements OnInit {
formBuilder: FormBuilder,
formValidationErrorService: FormValidationErrorsService,
loginService: LoginService,
ssoLoginService: SsoLoginServiceAbstraction,
webAuthnLoginService: WebAuthnLoginServiceAbstraction,
) {
super(
@@ -83,6 +85,7 @@ export class LoginComponent extends BaseLoginComponent implements OnInit {
formValidationErrorService,
route,
loginService,
ssoLoginService,
webAuthnLoginService,
);
this.onSuccessfulLogin = async () => {

View File

@@ -1,59 +1,9 @@
import { Component } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { SetPasswordComponent as BaseSetPasswordComponent } from "@bitwarden/angular/auth/components/set-password.component";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
import { DialogService } from "@bitwarden/components";
@Component({
selector: "app-set-password",
templateUrl: "set-password.component.html",
})
export class SetPasswordComponent extends BaseSetPasswordComponent {
constructor(
apiService: ApiService,
i18nService: I18nService,
cryptoService: CryptoService,
messagingService: MessagingService,
passwordGenerationService: PasswordGenerationServiceAbstraction,
platformUtilsService: PlatformUtilsService,
policyApiService: PolicyApiServiceAbstraction,
policyService: PolicyService,
router: Router,
syncService: SyncService,
route: ActivatedRoute,
stateService: StateService,
organizationApiService: OrganizationApiServiceAbstraction,
organizationUserService: OrganizationUserService,
dialogService: DialogService,
) {
super(
i18nService,
cryptoService,
messagingService,
passwordGenerationService,
platformUtilsService,
policyApiService,
policyService,
router,
apiService,
syncService,
route,
stateService,
organizationApiService,
organizationUserService,
dialogService,
);
}
}
export class SetPasswordComponent extends BaseSetPasswordComponent {}

View File

@@ -7,6 +7,7 @@ import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrgDomainApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization-domain/org-domain-api.service.abstraction";
import { OrganizationDomainSsoDetailsResponse } from "@bitwarden/common/admin-console/abstractions/organization-domain/responses/organization-domain-sso-details.response";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { HttpStatusCode } from "@bitwarden/common/enums";
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
@@ -26,6 +27,7 @@ import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/ge
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
export class SsoComponent extends BaseSsoComponent {
constructor(
ssoLoginService: SsoLoginServiceAbstraction,
loginStrategyService: LoginStrategyServiceAbstraction,
router: Router,
i18nService: I18nService,
@@ -42,6 +44,7 @@ export class SsoComponent extends BaseSsoComponent {
configService: ConfigServiceAbstraction,
) {
super(
ssoLoginService,
loginStrategyService,
router,
i18nService,
@@ -94,7 +97,7 @@ export class SsoComponent extends BaseSsoComponent {
}
// Fallback to state svc if domain is unclaimed
const storedIdentifier = await this.stateService.getSsoOrgIdentifier();
const storedIdentifier = await this.ssoLoginService.getOrganizationSsoIdentifier();
if (storedIdentifier != null) {
this.identifier = storedIdentifier;
}
@@ -118,7 +121,7 @@ export class SsoComponent extends BaseSsoComponent {
}
async submit() {
await this.stateService.setSsoOrganizationIdentifier(this.identifier);
await this.ssoLoginService.setOrganizationSsoIdentifier(this.identifier);
if (this.clientId === "browser") {
document.cookie = `ssoHandOffMessage=${this.i18nService.t("ssoHandOff")};SameSite=strict`;
}

View File

@@ -7,6 +7,7 @@ import { ModalService } from "@bitwarden/angular/services/modal.service";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
@@ -43,6 +44,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent implements OnDest
twoFactorService: TwoFactorService,
appIdService: AppIdService,
loginService: LoginService,
ssoLoginService: SsoLoginServiceAbstraction,
configService: ConfigServiceAbstraction,
@Inject(WINDOW) protected win: Window,
) {
@@ -60,6 +62,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent implements OnDest
twoFactorService,
appIdService,
loginService,
ssoLoginService,
configService,
);
this.onSuccessfulLoginNavigate = this.goAfterLogIn;

View File

@@ -5,6 +5,7 @@ import { SsoComponent } from "@bitwarden/angular/auth/components/sso.component";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
@@ -28,6 +29,7 @@ export class LinkSsoDirective extends SsoComponent implements AfterContentInit {
}
constructor(
ssoLoginService: SsoLoginServiceAbstraction,
platformUtilsService: PlatformUtilsService,
i18nService: I18nService,
apiService: ApiService,
@@ -42,6 +44,7 @@ export class LinkSsoDirective extends SsoComponent implements AfterContentInit {
configService: ConfigServiceAbstraction,
) {
super(
ssoLoginService,
loginStrategyService,
router,
i18nService,