mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-15 08:34:52 +00:00
feat: enforce oidc sso
This commit is contained in:
@@ -2,6 +2,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
import { organizationKeys } from "../organization/queries";
|
||||
import { oidcConfigKeys } from "./queries";
|
||||
|
||||
export const useUpdateOIDCConfig = () => {
|
||||
@@ -53,6 +54,7 @@ export const useUpdateOIDCConfig = () => {
|
||||
},
|
||||
onSuccess(_, dto) {
|
||||
queryClient.invalidateQueries(oidcConfigKeys.getOIDCConfig(dto.orgSlug));
|
||||
queryClient.invalidateQueries(organizationKeys.getUserOrganizations);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ export type Organization = {
|
||||
createAt: string;
|
||||
updatedAt: string;
|
||||
authEnforced: boolean;
|
||||
orgAuthMethod: string;
|
||||
scimEnabled: boolean;
|
||||
slug: string;
|
||||
};
|
||||
|
||||
@@ -9,7 +9,8 @@ export enum AuthMethod {
|
||||
AZURE_SAML = "azure-saml",
|
||||
JUMPCLOUD_SAML = "jumpcloud-saml",
|
||||
KEYCLOAK_SAML = "keycloak-saml",
|
||||
LDAP = "ldap"
|
||||
LDAP = "ldap",
|
||||
OIDC = "oidc"
|
||||
}
|
||||
|
||||
export type User = {
|
||||
|
||||
@@ -80,6 +80,7 @@ import { INTERNAL_KMS_KEY_ID } from "@app/hooks/api/kms/types";
|
||||
import { Workspace } from "@app/hooks/api/types";
|
||||
import { useUpdateUserProjectFavorites } from "@app/hooks/api/users/mutation";
|
||||
import { useGetUserProjectFavorites } from "@app/hooks/api/users/queries";
|
||||
import { AuthMethod } from "@app/hooks/api/users/types";
|
||||
import { navigateUserToOrg } from "@app/views/Login/Login.utils";
|
||||
import { CreateOrgModal } from "@app/views/Org/components";
|
||||
|
||||
@@ -385,9 +386,13 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
||||
// -> logout + redirect to SAML SSO
|
||||
|
||||
await logout.mutateAsync();
|
||||
window.open(
|
||||
`/api/v1/sso/redirect/saml2/organizations/${org.slug}`
|
||||
);
|
||||
if (org.orgAuthMethod === AuthMethod.OIDC) {
|
||||
window.open(`/api/v1/sso/oidc/login?orgSlug=${org.slug}`);
|
||||
} else {
|
||||
window.open(
|
||||
`/api/v1/sso/redirect/saml2/organizations/${org.slug}`
|
||||
);
|
||||
}
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import { useUser } from "@app/context";
|
||||
import { useGetOrganizations, useLogoutUser, useSelectOrganization } from "@app/hooks/api";
|
||||
import { UserAgentType } from "@app/hooks/api/auth/types";
|
||||
import { Organization } from "@app/hooks/api/types";
|
||||
import { AuthMethod } from "@app/hooks/api/users/types";
|
||||
import { getAuthToken, isLoggedIn } from "@app/reactQuery";
|
||||
import { navigateUserToOrg } from "@app/views/Login/Login.utils";
|
||||
|
||||
@@ -57,14 +58,21 @@ export default function LoginPage() {
|
||||
if (organization.authEnforced) {
|
||||
// org has an org-level auth method enabled (e.g. SAML)
|
||||
// -> logout + redirect to SAML SSO
|
||||
let samlUrl = `/api/v1/sso/redirect/saml2/organizations/${organization.slug}`;
|
||||
await logout.mutateAsync();
|
||||
let url = "";
|
||||
if (organization.orgAuthMethod === AuthMethod.OIDC) {
|
||||
url = `/api/v1/sso/oidc/login?orgSlug=${organization.slug}${
|
||||
callbackPort ? `&callbackPort=${callbackPort}` : ""
|
||||
}`;
|
||||
} else {
|
||||
url = `/api/v1/sso/redirect/saml2/organizations/${organization.slug}`;
|
||||
|
||||
if (callbackPort) {
|
||||
samlUrl += `?callback_port=${callbackPort}`;
|
||||
if (callbackPort) {
|
||||
url += `?callback_port=${callbackPort}`;
|
||||
}
|
||||
}
|
||||
|
||||
await logout.mutateAsync();
|
||||
window.open(samlUrl);
|
||||
window.open(url);
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
|
||||
+53
-1
@@ -7,7 +7,7 @@ import {
|
||||
useOrganization,
|
||||
useSubscription
|
||||
} from "@app/context";
|
||||
import { useGetOIDCConfig } from "@app/hooks/api";
|
||||
import { useGetOIDCConfig, useLogoutUser, useUpdateOrg } from "@app/hooks/api";
|
||||
import { useUpdateOIDCConfig } from "@app/hooks/api/oidcConfig/mutations";
|
||||
import { usePopUp } from "@app/hooks/usePopUp";
|
||||
|
||||
@@ -19,6 +19,9 @@ export const OrgOIDCSection = (): JSX.Element => {
|
||||
|
||||
const { data, isLoading } = useGetOIDCConfig(currentOrg?.slug ?? "");
|
||||
const { mutateAsync } = useUpdateOIDCConfig();
|
||||
const { mutateAsync: updateOrg } = useUpdateOrg();
|
||||
|
||||
const logout = useLogoutUser();
|
||||
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
|
||||
"addOIDC",
|
||||
"upgradePlan"
|
||||
@@ -51,6 +54,37 @@ export const OrgOIDCSection = (): JSX.Element => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleEnforceOrgAuthToggle = async (value: boolean) => {
|
||||
try {
|
||||
if (!currentOrg?.id) return;
|
||||
if (!subscription?.samlSSO) {
|
||||
handlePopUpOpen("upgradePlan");
|
||||
return;
|
||||
}
|
||||
|
||||
await updateOrg({
|
||||
orgId: currentOrg?.id,
|
||||
authEnforced: value
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: `Successfully ${value ? "enforced" : "un-enforced"} org-level auth`,
|
||||
type: "success"
|
||||
});
|
||||
|
||||
if (value) {
|
||||
await logout.mutateAsync();
|
||||
window.open(`/api/v1/sso/oidc/login?orgSlug=${currentOrg.slug}`);
|
||||
window.close();
|
||||
}
|
||||
} catch (err) {
|
||||
createNotification({
|
||||
text: (err as { response: { data: { message: string } } }).response.data.message,
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const addOidcButtonClick = async () => {
|
||||
if (subscription?.oidcSSO && currentOrg) {
|
||||
handlePopUpOpen("addOIDC");
|
||||
@@ -102,6 +136,24 @@ export const OrgOIDCSection = (): JSX.Element => {
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
<div className="py-4">
|
||||
<div className="mb-2 flex justify-between">
|
||||
<h3 className="text-md text-mineshaft-100">Enforce OIDC SSO</h3>
|
||||
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Sso}>
|
||||
{(isAllowed) => (
|
||||
<Switch
|
||||
id="enforce-org-auth"
|
||||
isChecked={currentOrg?.authEnforced ?? false}
|
||||
onCheckedChange={(value) => handleEnforceOrgAuthToggle(value)}
|
||||
isDisabled={!isAllowed}
|
||||
/>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
</div>
|
||||
<p className="text-sm text-mineshaft-300">
|
||||
Enforce members to authenticate via OIDC to access this organization
|
||||
</p>
|
||||
</div>
|
||||
<OIDCModal
|
||||
popUp={popUp}
|
||||
handlePopUpClose={handlePopUpClose}
|
||||
|
||||
Reference in New Issue
Block a user