mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-04 17:26:19 +00:00
Merge pull request #4501 from Infisical/ENG-3677
improvement(google-oauth-enforcement): prevent conflicting sso enforcement configuration
This commit is contained in:
@@ -127,6 +127,20 @@ export const ldapConfigServiceFactory = ({
|
|||||||
message:
|
message:
|
||||||
"Failed to create LDAP configuration due to plan restriction. Upgrade plan to create LDAP configuration."
|
"Failed to create LDAP configuration due to plan restriction. Upgrade plan to create LDAP configuration."
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const org = await orgDAL.findOrgById(orgId);
|
||||||
|
|
||||||
|
if (!org) {
|
||||||
|
throw new NotFoundError({ message: `Could not find organization with ID "${orgId}"` });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (org.googleSsoAuthEnforced && isActive) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"You cannot enable LDAP SSO while Google OAuth is enforced. Disable Google OAuth enforcement to enable LDAP SSO."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const { encryptor } = await kmsService.createCipherPairWithDataKey({
|
const { encryptor } = await kmsService.createCipherPairWithDataKey({
|
||||||
type: KmsDataKey.Organization,
|
type: KmsDataKey.Organization,
|
||||||
orgId
|
orgId
|
||||||
@@ -233,6 +247,19 @@ export const ldapConfigServiceFactory = ({
|
|||||||
"Failed to update LDAP configuration due to plan restriction. Upgrade plan to update LDAP configuration."
|
"Failed to update LDAP configuration due to plan restriction. Upgrade plan to update LDAP configuration."
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const org = await orgDAL.findOrgById(orgId);
|
||||||
|
|
||||||
|
if (!org) {
|
||||||
|
throw new NotFoundError({ message: `Could not find organization with ID "${orgId}"` });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (org.googleSsoAuthEnforced && isActive) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"You cannot enable LDAP SSO while Google OAuth is enforced. Disable Google OAuth enforcement to enable LDAP SSO."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const updateQuery: TLdapConfigsUpdate = {
|
const updateQuery: TLdapConfigsUpdate = {
|
||||||
isActive,
|
isActive,
|
||||||
url,
|
url,
|
||||||
|
|||||||
@@ -499,6 +499,13 @@ export const oidcConfigServiceFactory = ({
|
|||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Sso);
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Sso);
|
||||||
|
|
||||||
|
if (org.googleSsoAuthEnforced && isActive) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"You cannot enable OIDC SSO while Google OAuth is enforced. Disable Google OAuth enforcement to enable OIDC SSO."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const { encryptor } = await kmsService.createCipherPairWithDataKey({
|
const { encryptor } = await kmsService.createCipherPairWithDataKey({
|
||||||
type: KmsDataKey.Organization,
|
type: KmsDataKey.Organization,
|
||||||
orgId: org.id
|
orgId: org.id
|
||||||
@@ -586,6 +593,13 @@ export const oidcConfigServiceFactory = ({
|
|||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Sso);
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Sso);
|
||||||
|
|
||||||
|
if (org.googleSsoAuthEnforced && isActive) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"You cannot enable OIDC SSO while Google OAuth is enforced. Disable Google OAuth enforcement to enable OIDC SSO."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const { encryptor } = await kmsService.createCipherPairWithDataKey({
|
const { encryptor } = await kmsService.createCipherPairWithDataKey({
|
||||||
type: KmsDataKey.Organization,
|
type: KmsDataKey.Organization,
|
||||||
orgId: org.id
|
orgId: org.id
|
||||||
|
|||||||
@@ -82,6 +82,19 @@ export const samlConfigServiceFactory = ({
|
|||||||
"Failed to create SAML SSO configuration due to plan restriction. Upgrade plan to create SSO configuration."
|
"Failed to create SAML SSO configuration due to plan restriction. Upgrade plan to create SSO configuration."
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const org = await orgDAL.findOrgById(orgId);
|
||||||
|
|
||||||
|
if (!org) {
|
||||||
|
throw new NotFoundError({ message: `Could not find organization with ID "${orgId}"` });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (org.googleSsoAuthEnforced && isActive) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"You cannot enable SAML SSO while Google OAuth is enforced. Disable Google OAuth enforcement to enable SAML SSO."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const { encryptor } = await kmsService.createCipherPairWithDataKey({
|
const { encryptor } = await kmsService.createCipherPairWithDataKey({
|
||||||
type: KmsDataKey.Organization,
|
type: KmsDataKey.Organization,
|
||||||
orgId
|
orgId
|
||||||
@@ -120,6 +133,19 @@ export const samlConfigServiceFactory = ({
|
|||||||
"Failed to update SAML SSO configuration due to plan restriction. Upgrade plan to update SSO configuration."
|
"Failed to update SAML SSO configuration due to plan restriction. Upgrade plan to update SSO configuration."
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const org = await orgDAL.findOrgById(orgId);
|
||||||
|
|
||||||
|
if (!org) {
|
||||||
|
throw new NotFoundError({ message: `Could not find organization with ID "${orgId}"` });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (org.googleSsoAuthEnforced && isActive) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Cannot enable SAML SSO while Google OAuth is enforced. Disable Google OAuth enforcement to enable SAML SSO."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const updateQuery: TSamlConfigsUpdate = { authProvider, isActive, lastUsed: null };
|
const updateQuery: TSamlConfigsUpdate = { authProvider, isActive, lastUsed: null };
|
||||||
const { encryptor } = await kmsService.createCipherPairWithDataKey({
|
const { encryptor } = await kmsService.createCipherPairWithDataKey({
|
||||||
type: KmsDataKey.Organization,
|
type: KmsDataKey.Organization,
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
|
import { Cluster, Redis } from "ioredis";
|
||||||
|
|
||||||
import { buildRedisFromConfig, TRedisConfigKeys } from "@app/lib/config/redis";
|
import { buildRedisFromConfig, TRedisConfigKeys } from "@app/lib/config/redis";
|
||||||
import { pgAdvisoryLockHashText } from "@app/lib/crypto/hashtext";
|
import { pgAdvisoryLockHashText } from "@app/lib/crypto/hashtext";
|
||||||
import { applyJitter } from "@app/lib/dates";
|
import { applyJitter } from "@app/lib/dates";
|
||||||
import { delay as delayMs } from "@app/lib/delay";
|
import { delay as delayMs } from "@app/lib/delay";
|
||||||
import { ExecutionResult, Redlock, Settings } from "@app/lib/red-lock";
|
import { ExecutionResult, Redlock, Settings } from "@app/lib/red-lock";
|
||||||
import { Redis, Cluster } from "ioredis";
|
|
||||||
|
|
||||||
export const PgSqlLock = {
|
export const PgSqlLock = {
|
||||||
BootUpMigration: 2023,
|
BootUpMigration: 2023,
|
||||||
|
|||||||
@@ -807,6 +807,7 @@ export const registerRoutes = async (
|
|||||||
groupDAL,
|
groupDAL,
|
||||||
orgBotDAL,
|
orgBotDAL,
|
||||||
oidcConfigDAL,
|
oidcConfigDAL,
|
||||||
|
ldapConfigDAL,
|
||||||
loginService,
|
loginService,
|
||||||
projectBotService,
|
projectBotService,
|
||||||
reminderService
|
reminderService
|
||||||
|
|||||||
@@ -9,11 +9,14 @@ import {
|
|||||||
ProjectMembershipRole,
|
ProjectMembershipRole,
|
||||||
ProjectVersion,
|
ProjectVersion,
|
||||||
TableName,
|
TableName,
|
||||||
|
TOidcConfigs,
|
||||||
TProjectMemberships,
|
TProjectMemberships,
|
||||||
TProjectUserMembershipRolesInsert,
|
TProjectUserMembershipRolesInsert,
|
||||||
|
TSamlConfigs,
|
||||||
TUsers
|
TUsers
|
||||||
} from "@app/db/schemas";
|
} from "@app/db/schemas";
|
||||||
import { TGroupDALFactory } from "@app/ee/services/group/group-dal";
|
import { TGroupDALFactory } from "@app/ee/services/group/group-dal";
|
||||||
|
import { TLdapConfigDALFactory } from "@app/ee/services/ldap-config/ldap-config-dal";
|
||||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
import { TOidcConfigDALFactory } from "@app/ee/services/oidc/oidc-config-dal";
|
import { TOidcConfigDALFactory } from "@app/ee/services/oidc/oidc-config-dal";
|
||||||
import {
|
import {
|
||||||
@@ -125,6 +128,7 @@ type TOrgServiceFactoryDep = {
|
|||||||
incidentContactDAL: TIncidentContactsDALFactory;
|
incidentContactDAL: TIncidentContactsDALFactory;
|
||||||
samlConfigDAL: Pick<TSamlConfigDALFactory, "findOne">;
|
samlConfigDAL: Pick<TSamlConfigDALFactory, "findOne">;
|
||||||
oidcConfigDAL: Pick<TOidcConfigDALFactory, "findOne">;
|
oidcConfigDAL: Pick<TOidcConfigDALFactory, "findOne">;
|
||||||
|
ldapConfigDAL: Pick<TLdapConfigDALFactory, "findOne">;
|
||||||
smtpService: TSmtpService;
|
smtpService: TSmtpService;
|
||||||
tokenService: TAuthTokenServiceFactory;
|
tokenService: TAuthTokenServiceFactory;
|
||||||
permissionService: TPermissionServiceFactory;
|
permissionService: TPermissionServiceFactory;
|
||||||
@@ -165,6 +169,7 @@ export const orgServiceFactory = ({
|
|||||||
projectRoleDAL,
|
projectRoleDAL,
|
||||||
samlConfigDAL,
|
samlConfigDAL,
|
||||||
oidcConfigDAL,
|
oidcConfigDAL,
|
||||||
|
ldapConfigDAL,
|
||||||
projectUserMembershipRoleDAL,
|
projectUserMembershipRoleDAL,
|
||||||
identityMetadataDAL,
|
identityMetadataDAL,
|
||||||
projectBotService,
|
projectBotService,
|
||||||
@@ -446,16 +451,20 @@ export const orgServiceFactory = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authEnforced) {
|
let samlCfg: TSamlConfigs | undefined;
|
||||||
const samlCfg = await samlConfigDAL.findOne({
|
let oidcCfg: TOidcConfigs | undefined;
|
||||||
|
if (authEnforced || googleSsoAuthEnforced) {
|
||||||
|
samlCfg = await samlConfigDAL.findOne({
|
||||||
orgId,
|
orgId,
|
||||||
isActive: true
|
isActive: true
|
||||||
});
|
});
|
||||||
const oidcCfg = await oidcConfigDAL.findOne({
|
oidcCfg = await oidcConfigDAL.findOne({
|
||||||
orgId,
|
orgId,
|
||||||
isActive: true
|
isActive: true
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authEnforced) {
|
||||||
if (!samlCfg && !oidcCfg)
|
if (!samlCfg && !oidcCfg)
|
||||||
throw new NotFoundError({
|
throw new NotFoundError({
|
||||||
message: `SAML or OIDC configuration for organization with ID '${orgId}' not found`
|
message: `SAML or OIDC configuration for organization with ID '${orgId}' not found`
|
||||||
@@ -483,6 +492,32 @@ export const orgServiceFactory = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (samlCfg) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Cannot enable Google OAuth enforcement while SAML SSO is configured. Disable SAML SSO to enforce Google OAuth."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oidcCfg) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Cannot enable Google OAuth enforcement while OIDC SSO is configured. Disable OIDC SSO to enforce Google OAuth."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const ldapCfg = await ldapConfigDAL.findOne({
|
||||||
|
orgId,
|
||||||
|
isActive: true
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ldapCfg) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Cannot enable Google OAuth enforcement while LDAP SSO is configured. Disable LDAP SSO to enforce Google OAuth."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!currentOrg.googleSsoAuthLastUsed) {
|
if (!currentOrg.googleSsoAuthLastUsed) {
|
||||||
throw new BadRequestError({
|
throw new BadRequestError({
|
||||||
message:
|
message:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { FunctionComponent, ReactNode } from "react";
|
import { FunctionComponent, ReactNode } from "react";
|
||||||
import { BoundCanProps, Can } from "@casl/react";
|
import { BoundCanProps, Can } from "@casl/react";
|
||||||
|
|
||||||
|
import { TooltipProps } from "@app/components/v2/Tooltip/Tooltip";
|
||||||
import { TOrgPermission, useOrgPermission } from "@app/context/OrgPermissionContext";
|
import { TOrgPermission, useOrgPermission } from "@app/context/OrgPermissionContext";
|
||||||
|
|
||||||
import { AccessRestrictedBanner, Tooltip } from "../v2";
|
import { AccessRestrictedBanner, Tooltip } from "../v2";
|
||||||
@@ -20,6 +21,7 @@ type Props = {
|
|||||||
renderTooltip?: boolean;
|
renderTooltip?: boolean;
|
||||||
allowedLabel?: string;
|
allowedLabel?: string;
|
||||||
renderGuardBanner?: boolean;
|
renderGuardBanner?: boolean;
|
||||||
|
tooltipProps?: Omit<TooltipProps, "children">;
|
||||||
} & BoundCanProps<TOrgPermission>;
|
} & BoundCanProps<TOrgPermission>;
|
||||||
|
|
||||||
export const OrgPermissionCan: FunctionComponent<Props> = ({
|
export const OrgPermissionCan: FunctionComponent<Props> = ({
|
||||||
@@ -29,6 +31,7 @@ export const OrgPermissionCan: FunctionComponent<Props> = ({
|
|||||||
renderTooltip,
|
renderTooltip,
|
||||||
allowedLabel,
|
allowedLabel,
|
||||||
renderGuardBanner,
|
renderGuardBanner,
|
||||||
|
tooltipProps,
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const { permission } = useOrgPermission();
|
const { permission } = useOrgPermission();
|
||||||
@@ -43,11 +46,19 @@ export const OrgPermissionCan: FunctionComponent<Props> = ({
|
|||||||
: children;
|
: children;
|
||||||
|
|
||||||
if (!isAllowed && passThrough) {
|
if (!isAllowed && passThrough) {
|
||||||
return <Tooltip content={label}>{finalChild}</Tooltip>;
|
return (
|
||||||
|
<Tooltip content={label} {...tooltipProps}>
|
||||||
|
{finalChild}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAllowed && renderTooltip && allowedLabel) {
|
if (isAllowed && renderTooltip && allowedLabel) {
|
||||||
return <Tooltip content={allowedLabel}>{finalChild}</Tooltip>;
|
return (
|
||||||
|
<Tooltip content={allowedLabel} {...tooltipProps}>
|
||||||
|
{finalChild}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isAllowed && renderGuardBanner) {
|
if (!isAllowed && renderGuardBanner) {
|
||||||
|
|||||||
+53
-17
@@ -24,11 +24,17 @@ enum EnforceAuthType {
|
|||||||
export const OrgGeneralAuthSection = ({
|
export const OrgGeneralAuthSection = ({
|
||||||
isSamlConfigured,
|
isSamlConfigured,
|
||||||
isOidcConfigured,
|
isOidcConfigured,
|
||||||
isGoogleConfigured
|
isGoogleConfigured,
|
||||||
|
isSamlActive,
|
||||||
|
isOidcActive,
|
||||||
|
isLdapActive
|
||||||
}: {
|
}: {
|
||||||
isSamlConfigured: boolean;
|
isSamlConfigured: boolean;
|
||||||
isOidcConfigured: boolean;
|
isOidcConfigured: boolean;
|
||||||
isGoogleConfigured: boolean;
|
isGoogleConfigured: boolean;
|
||||||
|
isSamlActive: boolean;
|
||||||
|
isOidcActive: boolean;
|
||||||
|
isLdapActive: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const { currentOrg } = useOrganization();
|
const { currentOrg } = useOrganization();
|
||||||
const { subscription } = useSubscription();
|
const { subscription } = useSubscription();
|
||||||
@@ -126,6 +132,15 @@ export const OrgGeneralAuthSection = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isGoogleOAuthEnforced = currentOrg.googleSsoAuthEnforced;
|
||||||
|
|
||||||
|
const getActiveSsoLabel = () => {
|
||||||
|
if (isSamlActive) return "SAML";
|
||||||
|
if (isOidcActive) return "OIDC";
|
||||||
|
if (isLdapActive) return "LDAP";
|
||||||
|
return "";
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-6">
|
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-6">
|
||||||
<div>
|
<div>
|
||||||
@@ -135,7 +150,7 @@ export const OrgGeneralAuthSection = ({
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-2 py-4">
|
<div className="flex flex-col gap-2 py-4">
|
||||||
<div className={twMerge("mt-4", !isSamlConfigured && "hidden")}>
|
<div className={twMerge("mt-4", (!isSamlConfigured || isGoogleOAuthEnforced) && "hidden")}>
|
||||||
<div className="mb-2 flex justify-between">
|
<div className="mb-2 flex justify-between">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<span className="text-md text-mineshaft-100">Enforce SAML SSO</span>
|
<span className="text-md text-mineshaft-100">Enforce SAML SSO</span>
|
||||||
@@ -160,7 +175,7 @@ export const OrgGeneralAuthSection = ({
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={twMerge("mt-4", !isOidcConfigured && "hidden")}>
|
<div className={twMerge("mt-4", (!isOidcConfigured || isGoogleOAuthEnforced) && "hidden")}>
|
||||||
<div className="mb-2 flex justify-between">
|
<div className="mb-2 flex justify-between">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<span className="text-md text-mineshaft-100">Enforce OIDC SSO</span>
|
<span className="text-md text-mineshaft-100">Enforce OIDC SSO</span>
|
||||||
@@ -188,26 +203,47 @@ export const OrgGeneralAuthSection = ({
|
|||||||
<div className={twMerge("mt-2", !isGoogleConfigured && "hidden")}>
|
<div className={twMerge("mt-2", !isGoogleConfigured && "hidden")}>
|
||||||
<div className="mb-2 flex justify-between">
|
<div className="mb-2 flex justify-between">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<span className="text-md text-mineshaft-100">Enforce Google SSO</span>
|
<span className="text-md text-mineshaft-100">Enforce Google OAuth</span>
|
||||||
</div>
|
</div>
|
||||||
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Sso}>
|
<OrgPermissionCan
|
||||||
|
I={OrgPermissionActions.Edit}
|
||||||
|
a={OrgPermissionSubjects.Sso}
|
||||||
|
tooltipProps={{
|
||||||
|
className: "max-w-sm",
|
||||||
|
side: "left"
|
||||||
|
}}
|
||||||
|
allowedLabel={
|
||||||
|
isOidcActive || isSamlActive || isLdapActive
|
||||||
|
? `You cannot enforce Google OAuth while ${getActiveSsoLabel()} SSO is enabled. Disable ${getActiveSsoLabel()} SSO to enforce Google OAuth.`
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
renderTooltip={isOidcActive || isSamlActive || isLdapActive}
|
||||||
|
>
|
||||||
{(isAllowed) => (
|
{(isAllowed) => (
|
||||||
<Switch
|
<div>
|
||||||
id="enforce-google-sso"
|
<Switch
|
||||||
onCheckedChange={(value) =>
|
id="enforce-google-sso"
|
||||||
handleEnforceOrgAuthToggle(value, EnforceAuthType.GOOGLE)
|
onCheckedChange={(value) =>
|
||||||
}
|
handleEnforceOrgAuthToggle(value, EnforceAuthType.GOOGLE)
|
||||||
isChecked={currentOrg?.googleSsoAuthEnforced ?? false}
|
}
|
||||||
isDisabled={!isAllowed || currentOrg?.authEnforced}
|
isChecked={currentOrg?.googleSsoAuthEnforced ?? false}
|
||||||
/>
|
isDisabled={
|
||||||
|
!isAllowed ||
|
||||||
|
currentOrg?.authEnforced ||
|
||||||
|
isOidcActive ||
|
||||||
|
isSamlActive ||
|
||||||
|
isLdapActive
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</OrgPermissionCan>
|
</OrgPermissionCan>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-mineshaft-300">
|
<p className="text-sm text-mineshaft-300">
|
||||||
Enforce users to authenticate via Google OAuth SSO to access this organization.
|
Enforce users to authenticate via Google OAuth to access this organization.
|
||||||
<br />
|
<br />
|
||||||
When this is enabled your organization members will only be able to login with Google
|
When this is enabled your organization members will only be able to login with Google
|
||||||
SSO (not Google SAML).
|
OAuth (not Google SAML).
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -267,8 +303,8 @@ export const OrgGeneralAuthSection = ({
|
|||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-mineshaft-300">
|
<p className="text-sm text-mineshaft-300">
|
||||||
<span>
|
<span>
|
||||||
Allow organization admins to bypass SAML enforcement when SSO is unavailable,
|
Allow organization admins to bypass SSO login enforcement when your SSO provider is
|
||||||
misconfigured, or inaccessible.
|
unavailable, misconfigured, or inaccessible.
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+26
-9
@@ -94,6 +94,8 @@ export const OrgLDAPSection = (): JSX.Element => {
|
|||||||
handlePopUpOpen("ldapGroupMap");
|
handlePopUpOpen("ldapGroupMap");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isGoogleOAuthEnabled = currentOrg.googleSsoAuthEnforced;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
@@ -116,16 +118,31 @@ export const OrgLDAPSection = (): JSX.Element => {
|
|||||||
<div className="pt-4">
|
<div className="pt-4">
|
||||||
<div className="mb-2 flex items-center justify-between">
|
<div className="mb-2 flex items-center justify-between">
|
||||||
<h2 className="text-md text-mineshaft-100">Enable LDAP</h2>
|
<h2 className="text-md text-mineshaft-100">Enable LDAP</h2>
|
||||||
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Ldap}>
|
<OrgPermissionCan
|
||||||
|
I={OrgPermissionActions.Edit}
|
||||||
|
a={OrgPermissionSubjects.Ldap}
|
||||||
|
tooltipProps={{
|
||||||
|
className: "max-w-sm",
|
||||||
|
side: "left"
|
||||||
|
}}
|
||||||
|
allowedLabel={
|
||||||
|
isGoogleOAuthEnabled
|
||||||
|
? "You cannot enable LDAP SSO while Google OAuth is enforced. Disable Google OAuth enforcement to enable LDAP SSO."
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
renderTooltip={isGoogleOAuthEnabled}
|
||||||
|
>
|
||||||
{(isAllowed) => (
|
{(isAllowed) => (
|
||||||
<Switch
|
<div>
|
||||||
id="enable-saml-sso"
|
<Switch
|
||||||
onCheckedChange={(value) => handleLDAPToggle(value)}
|
id="enable-ldap-sso"
|
||||||
isChecked={data ? data.isActive : false}
|
onCheckedChange={(value) => handleLDAPToggle(value)}
|
||||||
isDisabled={!isAllowed}
|
isChecked={data ? data.isActive : false}
|
||||||
>
|
isDisabled={!isAllowed || isGoogleOAuthEnabled}
|
||||||
Enable
|
>
|
||||||
</Switch>
|
Enable
|
||||||
|
</Switch>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</OrgPermissionCan>
|
</OrgPermissionCan>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+24
-7
@@ -83,6 +83,8 @@ export const OrgOIDCSection = (): JSX.Element => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isGoogleOAuthEnabled = currentOrg.googleSsoAuthEnforced;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-4 rounded-lg border-mineshaft-600 bg-mineshaft-900">
|
<div className="mb-4 rounded-lg border-mineshaft-600 bg-mineshaft-900">
|
||||||
<div className="mb-4 flex items-center justify-between">
|
<div className="mb-4 flex items-center justify-between">
|
||||||
@@ -106,14 +108,29 @@ export const OrgOIDCSection = (): JSX.Element => {
|
|||||||
<div className="mb-2 flex items-center justify-between">
|
<div className="mb-2 flex items-center justify-between">
|
||||||
<h2 className="text-md text-mineshaft-100">Enable OIDC</h2>
|
<h2 className="text-md text-mineshaft-100">Enable OIDC</h2>
|
||||||
{!isPending && (
|
{!isPending && (
|
||||||
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Sso}>
|
<OrgPermissionCan
|
||||||
|
I={OrgPermissionActions.Edit}
|
||||||
|
a={OrgPermissionSubjects.Sso}
|
||||||
|
tooltipProps={{
|
||||||
|
className: "max-w-sm",
|
||||||
|
side: "left"
|
||||||
|
}}
|
||||||
|
allowedLabel={
|
||||||
|
isGoogleOAuthEnabled
|
||||||
|
? "You cannot enable OIDC SSO while Google OAuth is enforced. Disable Google OAuth enforcement to enable OIDC SSO."
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
renderTooltip={isGoogleOAuthEnabled}
|
||||||
|
>
|
||||||
{(isAllowed) => (
|
{(isAllowed) => (
|
||||||
<Switch
|
<div>
|
||||||
id="enable-oidc-sso"
|
<Switch
|
||||||
onCheckedChange={(value) => handleOIDCToggle(value)}
|
id="enable-oidc-sso"
|
||||||
isChecked={data ? data.isActive : false}
|
onCheckedChange={(value) => handleOIDCToggle(value)}
|
||||||
isDisabled={!isAllowed}
|
isChecked={data ? data.isActive : false}
|
||||||
/>
|
isDisabled={!isAllowed || isGoogleOAuthEnabled}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</OrgPermissionCan>
|
</OrgPermissionCan>
|
||||||
)}
|
)}
|
||||||
|
|||||||
+24
-7
@@ -78,6 +78,8 @@ export const OrgSSOSection = (): JSX.Element => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isGoogleOAuthEnabled = currentOrg.googleSsoAuthEnforced;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="mb-4 flex items-center justify-between">
|
<div className="mb-4 flex items-center justify-between">
|
||||||
@@ -99,14 +101,29 @@ export const OrgSSOSection = (): JSX.Element => {
|
|||||||
<div className="mb-2 flex items-center justify-between pt-4">
|
<div className="mb-2 flex items-center justify-between pt-4">
|
||||||
<h2 className="text-md text-mineshaft-100">Enable SAML</h2>
|
<h2 className="text-md text-mineshaft-100">Enable SAML</h2>
|
||||||
{!isPending && (
|
{!isPending && (
|
||||||
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Sso}>
|
<OrgPermissionCan
|
||||||
|
I={OrgPermissionActions.Edit}
|
||||||
|
a={OrgPermissionSubjects.Sso}
|
||||||
|
tooltipProps={{
|
||||||
|
className: "max-w-sm",
|
||||||
|
side: "left"
|
||||||
|
}}
|
||||||
|
allowedLabel={
|
||||||
|
isGoogleOAuthEnabled
|
||||||
|
? "You cannot enable SAML SSO while Google OAuth is enforced. Disable Google OAuth enforcement to enable SAML SSO."
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
renderTooltip={isGoogleOAuthEnabled}
|
||||||
|
>
|
||||||
{(isAllowed) => (
|
{(isAllowed) => (
|
||||||
<Switch
|
<div>
|
||||||
id="enable-saml-sso"
|
<Switch
|
||||||
onCheckedChange={(value) => handleSamlSSOToggle(value)}
|
id="enable-saml-sso"
|
||||||
isChecked={data ? data.isActive : false}
|
onCheckedChange={(value) => handleSamlSSOToggle(value)}
|
||||||
isDisabled={!isAllowed}
|
isChecked={data ? data.isActive : false}
|
||||||
/>
|
isDisabled={!isAllowed || isGoogleOAuthEnabled}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</OrgPermissionCan>
|
</OrgPermissionCan>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -184,6 +184,9 @@ export const OrgSsoTab = withPermission(
|
|||||||
isSamlConfigured={isSamlConfigured}
|
isSamlConfigured={isSamlConfigured}
|
||||||
isOidcConfigured={isOidcConfigured}
|
isOidcConfigured={isOidcConfigured}
|
||||||
isGoogleConfigured={isGoogleConfigured}
|
isGoogleConfigured={isGoogleConfigured}
|
||||||
|
isSamlActive={Boolean(samlConfig?.isActive)}
|
||||||
|
isOidcActive={Boolean(oidcConfig?.isActive)}
|
||||||
|
isLdapActive={Boolean(ldapConfig?.isActive)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user