mirror of
https://github.com/bitwarden/browser.git
synced 2024-10-14 06:48:18 +02:00
[PM-12357] - Using new Verified SSO Domain call for SSO (#11446)
* Added new SSO verified domain call and added calling of it behind feature flag.
This commit is contained in:
parent
e2275ad0bc
commit
1ca03e7815
@ -12,11 +12,14 @@ import {
|
|||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { OrgDomainApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization-domain/org-domain-api.service.abstraction";
|
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 { OrganizationDomainSsoDetailsResponse } from "@bitwarden/common/admin-console/abstractions/organization-domain/responses/organization-domain-sso-details.response";
|
||||||
|
import { VerifiedOrganizationDomainSsoDetailsResponse } from "@bitwarden/common/admin-console/abstractions/organization-domain/responses/verified-organization-domain-sso-details.response";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
||||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||||
import { HttpStatusCode } from "@bitwarden/common/enums";
|
import { HttpStatusCode } from "@bitwarden/common/enums";
|
||||||
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||||
|
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.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";
|
||||||
@ -107,13 +110,24 @@ export class SsoComponent extends BaseSsoComponent implements OnInit {
|
|||||||
// show loading spinner
|
// show loading spinner
|
||||||
this.loggingIn = true;
|
this.loggingIn = true;
|
||||||
try {
|
try {
|
||||||
const response: OrganizationDomainSsoDetailsResponse =
|
if (await this.configService.getFeatureFlag(FeatureFlag.VerifiedSsoDomainEndpoint)) {
|
||||||
await this.orgDomainApiService.getClaimedOrgDomainByEmail(qParams.email);
|
const response: ListResponse<VerifiedOrganizationDomainSsoDetailsResponse> =
|
||||||
|
await this.orgDomainApiService.getVerifiedOrgDomainsByEmail(qParams.email);
|
||||||
|
|
||||||
if (response?.ssoAvailable && response?.verifiedDate) {
|
if (response.data.length > 0) {
|
||||||
this.identifierFormControl.setValue(response.organizationIdentifier);
|
this.identifierFormControl.setValue(response.data[0].organizationIdentifier);
|
||||||
await this.submit();
|
await this.submit();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const response: OrganizationDomainSsoDetailsResponse =
|
||||||
|
await this.orgDomainApiService.getClaimedOrgDomainByEmail(qParams.email);
|
||||||
|
|
||||||
|
if (response?.ssoAvailable && response?.verifiedDate) {
|
||||||
|
this.identifierFormControl.setValue(response.organizationIdentifier);
|
||||||
|
await this.submit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleGetClaimedDomainByEmailError(error);
|
this.handleGetClaimedDomainByEmailError(error);
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
|
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||||
|
|
||||||
import { OrganizationDomainRequest } from "../../services/organization-domain/requests/organization-domain.request";
|
import { OrganizationDomainRequest } from "../../services/organization-domain/requests/organization-domain.request";
|
||||||
|
|
||||||
import { OrganizationDomainSsoDetailsResponse } from "./responses/organization-domain-sso-details.response";
|
import { OrganizationDomainSsoDetailsResponse } from "./responses/organization-domain-sso-details.response";
|
||||||
import { OrganizationDomainResponse } from "./responses/organization-domain.response";
|
import { OrganizationDomainResponse } from "./responses/organization-domain.response";
|
||||||
|
import { VerifiedOrganizationDomainSsoDetailsResponse } from "./responses/verified-organization-domain-sso-details.response";
|
||||||
|
|
||||||
export abstract class OrgDomainApiServiceAbstraction {
|
export abstract class OrgDomainApiServiceAbstraction {
|
||||||
getAllByOrgId: (orgId: string) => Promise<Array<OrganizationDomainResponse>>;
|
getAllByOrgId: (orgId: string) => Promise<Array<OrganizationDomainResponse>>;
|
||||||
@ -16,4 +19,7 @@ export abstract class OrgDomainApiServiceAbstraction {
|
|||||||
verify: (orgId: string, orgDomainId: string) => Promise<OrganizationDomainResponse>;
|
verify: (orgId: string, orgDomainId: string) => Promise<OrganizationDomainResponse>;
|
||||||
delete: (orgId: string, orgDomainId: string) => Promise<any>;
|
delete: (orgId: string, orgDomainId: string) => Promise<any>;
|
||||||
getClaimedOrgDomainByEmail: (email: string) => Promise<OrganizationDomainSsoDetailsResponse>;
|
getClaimedOrgDomainByEmail: (email: string) => Promise<OrganizationDomainSsoDetailsResponse>;
|
||||||
|
getVerifiedOrgDomainsByEmail: (
|
||||||
|
email: string,
|
||||||
|
) => Promise<ListResponse<VerifiedOrganizationDomainSsoDetailsResponse>>;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
import { BaseResponse } from "@bitwarden/common/models/response/base.response";
|
||||||
|
|
||||||
|
export class VerifiedOrganizationDomainSsoDetailsResponse extends BaseResponse {
|
||||||
|
organizationName: string;
|
||||||
|
organizationIdentifier: string;
|
||||||
|
domainName: string;
|
||||||
|
|
||||||
|
constructor(response: any) {
|
||||||
|
super(response);
|
||||||
|
|
||||||
|
this.organizationName = this.getResponseProperty("organizationName");
|
||||||
|
this.organizationIdentifier = this.getResponseProperty("organizationIdentifier");
|
||||||
|
this.domainName = this.getResponseProperty("domainName");
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,9 @@
|
|||||||
import { mock } from "jest-mock-extended";
|
import { mock } from "jest-mock-extended";
|
||||||
import { lastValueFrom } from "rxjs";
|
import { lastValueFrom } from "rxjs";
|
||||||
|
|
||||||
|
import { VerifiedOrganizationDomainSsoDetailsResponse } from "@bitwarden/common/admin-console/abstractions/organization-domain/responses/verified-organization-domain-sso-details.response";
|
||||||
|
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||||
|
|
||||||
import { ApiService } from "../../../abstractions/api.service";
|
import { ApiService } from "../../../abstractions/api.service";
|
||||||
import { I18nService } from "../../../platform/abstractions/i18n.service";
|
import { I18nService } from "../../../platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "../../../platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "../../../platform/abstractions/platform-utils.service";
|
||||||
@ -81,6 +84,19 @@ const mockedOrganizationDomainSsoDetailsResponse = new OrganizationDomainSsoDeta
|
|||||||
mockedOrganizationDomainSsoDetailsServerResponse,
|
mockedOrganizationDomainSsoDetailsServerResponse,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const mockedVerifiedOrganizationDomain = {
|
||||||
|
organizationIdentifier: "fake-org-identifier",
|
||||||
|
organizationName: "fake-org",
|
||||||
|
domainName: "fake-domain-name",
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockedVerifiedOrganizationDomainSsoResponse =
|
||||||
|
new VerifiedOrganizationDomainSsoDetailsResponse(mockedVerifiedOrganizationDomain);
|
||||||
|
|
||||||
|
const mockedVerifiedOrganizationDomainSsoDetailsListResponse = {
|
||||||
|
data: [mockedVerifiedOrganizationDomain],
|
||||||
|
} as ListResponse<VerifiedOrganizationDomainSsoDetailsResponse>;
|
||||||
|
|
||||||
describe("Org Domain API Service", () => {
|
describe("Org Domain API Service", () => {
|
||||||
let orgDomainApiService: OrgDomainApiService;
|
let orgDomainApiService: OrgDomainApiService;
|
||||||
|
|
||||||
@ -229,4 +245,21 @@ describe("Org Domain API Service", () => {
|
|||||||
|
|
||||||
expect(result).toEqual(mockedOrganizationDomainSsoDetailsResponse);
|
expect(result).toEqual(mockedOrganizationDomainSsoDetailsResponse);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("getVerifiedOrgDomainsByEmail should call ApiService.send with correct parameters and return response", async () => {
|
||||||
|
const email = "test@example.com";
|
||||||
|
apiService.send.mockResolvedValue(mockedVerifiedOrganizationDomainSsoDetailsListResponse);
|
||||||
|
|
||||||
|
const result = await orgDomainApiService.getVerifiedOrgDomainsByEmail(email);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"POST",
|
||||||
|
"/organizations/domain/sso/verified",
|
||||||
|
new OrganizationDomainSsoDetailsRequest(email),
|
||||||
|
false, //anonymous
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.data).toContainEqual(mockedVerifiedOrganizationDomainSsoResponse);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -4,6 +4,7 @@ import { OrgDomainApiServiceAbstraction } from "../../abstractions/organization-
|
|||||||
import { OrgDomainInternalServiceAbstraction } from "../../abstractions/organization-domain/org-domain.service.abstraction";
|
import { OrgDomainInternalServiceAbstraction } from "../../abstractions/organization-domain/org-domain.service.abstraction";
|
||||||
import { OrganizationDomainSsoDetailsResponse } from "../../abstractions/organization-domain/responses/organization-domain-sso-details.response";
|
import { OrganizationDomainSsoDetailsResponse } from "../../abstractions/organization-domain/responses/organization-domain-sso-details.response";
|
||||||
import { OrganizationDomainResponse } from "../../abstractions/organization-domain/responses/organization-domain.response";
|
import { OrganizationDomainResponse } from "../../abstractions/organization-domain/responses/organization-domain.response";
|
||||||
|
import { VerifiedOrganizationDomainSsoDetailsResponse } from "../../abstractions/organization-domain/responses/verified-organization-domain-sso-details.response";
|
||||||
|
|
||||||
import { OrganizationDomainSsoDetailsRequest } from "./requests/organization-domain-sso-details.request";
|
import { OrganizationDomainSsoDetailsRequest } from "./requests/organization-domain-sso-details.request";
|
||||||
import { OrganizationDomainRequest } from "./requests/organization-domain.request";
|
import { OrganizationDomainRequest } from "./requests/organization-domain.request";
|
||||||
@ -109,4 +110,18 @@ export class OrgDomainApiService implements OrgDomainApiServiceAbstraction {
|
|||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getVerifiedOrgDomainsByEmail(
|
||||||
|
email: string,
|
||||||
|
): Promise<ListResponse<VerifiedOrganizationDomainSsoDetailsResponse>> {
|
||||||
|
const result = await this.apiService.send(
|
||||||
|
"POST",
|
||||||
|
`/organizations/domain/sso/verified`,
|
||||||
|
new OrganizationDomainSsoDetailsRequest(email),
|
||||||
|
false, // anonymous
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
return new ListResponse(result, VerifiedOrganizationDomainSsoDetailsResponse);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ export enum FeatureFlag {
|
|||||||
NotificationBarAddLoginImprovements = "notification-bar-add-login-improvements",
|
NotificationBarAddLoginImprovements = "notification-bar-add-login-improvements",
|
||||||
AC2476_DeprecateStripeSourcesAPI = "AC-2476-deprecate-stripe-sources-api",
|
AC2476_DeprecateStripeSourcesAPI = "AC-2476-deprecate-stripe-sources-api",
|
||||||
CipherKeyEncryption = "cipher-key-encryption",
|
CipherKeyEncryption = "cipher-key-encryption",
|
||||||
|
VerifiedSsoDomainEndpoint = "pm-12337-refactor-sso-details-endpoint",
|
||||||
PM11901_RefactorSelfHostingLicenseUploader = "PM-11901-refactor-self-hosting-license-uploader",
|
PM11901_RefactorSelfHostingLicenseUploader = "PM-11901-refactor-self-hosting-license-uploader",
|
||||||
Pm3478RefactorOrganizationUserApi = "pm-3478-refactor-organizationuser-api",
|
Pm3478RefactorOrganizationUserApi = "pm-3478-refactor-organizationuser-api",
|
||||||
AccessIntelligence = "pm-13227-access-intelligence",
|
AccessIntelligence = "pm-13227-access-intelligence",
|
||||||
@ -75,6 +76,7 @@ export const DefaultFeatureFlagValue = {
|
|||||||
[FeatureFlag.NotificationBarAddLoginImprovements]: FALSE,
|
[FeatureFlag.NotificationBarAddLoginImprovements]: FALSE,
|
||||||
[FeatureFlag.AC2476_DeprecateStripeSourcesAPI]: FALSE,
|
[FeatureFlag.AC2476_DeprecateStripeSourcesAPI]: FALSE,
|
||||||
[FeatureFlag.CipherKeyEncryption]: FALSE,
|
[FeatureFlag.CipherKeyEncryption]: FALSE,
|
||||||
|
[FeatureFlag.VerifiedSsoDomainEndpoint]: FALSE,
|
||||||
[FeatureFlag.PM11901_RefactorSelfHostingLicenseUploader]: FALSE,
|
[FeatureFlag.PM11901_RefactorSelfHostingLicenseUploader]: FALSE,
|
||||||
[FeatureFlag.Pm3478RefactorOrganizationUserApi]: FALSE,
|
[FeatureFlag.Pm3478RefactorOrganizationUserApi]: FALSE,
|
||||||
[FeatureFlag.AccessIntelligence]: FALSE,
|
[FeatureFlag.AccessIntelligence]: FALSE,
|
||||||
|
Loading…
Reference in New Issue
Block a user