Revise SAML flow, update Okta SAML docs

This commit is contained in:
Tuan Dang
2023-07-29 01:57:07 +07:00
parent ed2cf68935
commit cc4b749ce8
22 changed files with 131 additions and 174 deletions
+2 -28
View File
@@ -57,7 +57,6 @@ export const updateSSOConfig = async (req: Request, res: Response) => {
entryPoint, entryPoint,
issuer, issuer,
cert, cert,
audience
} = req.body; } = req.body;
const plan = await EELicenseService.getPlan(organizationId); const plan = await EELicenseService.getPlan(organizationId);
@@ -78,9 +77,6 @@ export const updateSSOConfig = async (req: Request, res: Response) => {
encryptedCert?: string; encryptedCert?: string;
certIV?: string; certIV?: string;
certTag?: string; certTag?: string;
encryptedAudience?: string;
audienceIV?: string;
audienceTag?: string;
} }
const update: PatchUpdate = {}; const update: PatchUpdate = {};
@@ -132,18 +128,6 @@ export const updateSSOConfig = async (req: Request, res: Response) => {
update.certIV = certIV; update.certIV = certIV;
update.certTag = certTag; update.certTag = certTag;
} }
if (audience) {
const {
ciphertext: encryptedAudience,
iv: audienceIV,
tag: audienceTag
} = client.encryptSymmetric(audience, key);
update.encryptedAudience = encryptedAudience;
update.audienceIV = audienceIV;
update.audienceTag = audienceTag;
}
const ssoConfig = await SSOConfig.findOneAndUpdate( const ssoConfig = await SSOConfig.findOneAndUpdate(
{ {
@@ -207,8 +191,7 @@ export const createSSOConfig = async (req: Request, res: Response) => {
isActive, isActive,
entryPoint, entryPoint,
issuer, issuer,
cert, cert
audience
} = req.body; } = req.body;
const plan = await EELicenseService.getPlan(organizationId); const plan = await EELicenseService.getPlan(organizationId);
@@ -238,12 +221,6 @@ export const createSSOConfig = async (req: Request, res: Response) => {
iv: certIV, iv: certIV,
tag: certTag tag: certTag
} = client.encryptSymmetric(cert, key); } = client.encryptSymmetric(cert, key);
const {
ciphertext: encryptedAudience,
iv: audienceIV,
tag: audienceTag
} = client.encryptSymmetric(audience, key);
const ssoConfig = await new SSOConfig({ const ssoConfig = await new SSOConfig({
organization: new Types.ObjectId(organizationId), organization: new Types.ObjectId(organizationId),
@@ -257,10 +234,7 @@ export const createSSOConfig = async (req: Request, res: Response) => {
issuerTag, issuerTag,
encryptedCert, encryptedCert,
certIV, certIV,
certTag, certTag
encryptedAudience,
audienceIV,
audienceTag
}).save(); }).save();
return res.status(200).send(ssoConfig); return res.status(200).send(ssoConfig);
+1 -9
View File
@@ -51,13 +51,6 @@ export const getSSOConfigHelper = async ({
ssoConfig.certIV, ssoConfig.certIV,
ssoConfig.certTag ssoConfig.certTag
); );
const audience = client.decryptSymmetric(
ssoConfig.encryptedAudience,
key,
ssoConfig.audienceIV,
ssoConfig.audienceTag
);
return ({ return ({
_id: ssoConfig._id, _id: ssoConfig._id,
@@ -66,7 +59,6 @@ export const getSSOConfigHelper = async ({
isActive: ssoConfig.isActive, isActive: ssoConfig.isActive,
entryPoint, entryPoint,
issuer, issuer,
cert, cert
audience
}); });
} }
+6 -16
View File
@@ -1,8 +1,12 @@
import { Schema, Types, model } from "mongoose"; import { Schema, Types, model } from "mongoose";
export enum AuthProvider {
OKTA_SAML = "okta-saml"
}
export interface ISSOConfig { export interface ISSOConfig {
organization: Types.ObjectId; organization: Types.ObjectId;
authProvider: "okta-saml" authProvider: AuthProvider;
isActive: boolean; isActive: boolean;
encryptedEntryPoint: string; encryptedEntryPoint: string;
entryPointIV: string; entryPointIV: string;
@@ -13,9 +17,6 @@ export interface ISSOConfig {
encryptedCert: string; encryptedCert: string;
certIV: string; certIV: string;
certTag: string; certTag: string;
encryptedAudience: string;
audienceIV: string;
audienceTag: string;
} }
const ssoConfigSchema = new Schema<ISSOConfig>( const ssoConfigSchema = new Schema<ISSOConfig>(
@@ -26,9 +27,7 @@ const ssoConfigSchema = new Schema<ISSOConfig>(
}, },
authProvider: { authProvider: {
type: String, type: String,
enum: [ enum: AuthProvider,
"okta-saml"
],
required: true required: true
}, },
isActive: { isActive: {
@@ -61,15 +60,6 @@ const ssoConfigSchema = new Schema<ISSOConfig>(
}, },
certTag: { certTag: {
type: String type: String
},
encryptedAudience: {
type: String
},
audienceIV: {
type: String
},
audienceTag: {
type: String
} }
}, },
{ {
+4 -3
View File
@@ -1,6 +1,9 @@
import express from "express"; import express from "express";
const router = express.Router(); const router = express.Router();
import passport from "passport"; import passport from "passport";
import {
AuthProvider
} from "../../models";
import { import {
requireAuth, requireAuth,
requireOrganizationAuth, requireOrganizationAuth,
@@ -87,12 +90,11 @@ router.post(
locationOrganizationId: "body" locationOrganizationId: "body"
}), }),
body("organizationId").exists().trim(), body("organizationId").exists().trim(),
body("authProvider").exists().isString(), body("authProvider").exists().isString().isIn([AuthProvider.OKTA_SAML]),
body("isActive").exists().isBoolean(), body("isActive").exists().isBoolean(),
body("entryPoint").exists().isString(), body("entryPoint").exists().isString(),
body("issuer").exists().isString(), body("issuer").exists().isString(),
body("cert").exists().isString(), body("cert").exists().isString(),
body("audience").exists().isString(),
validateRequest, validateRequest,
ssoController.createSSOConfig ssoController.createSSOConfig
); );
@@ -113,7 +115,6 @@ router.patch(
body("entryPoint").optional().isString(), body("entryPoint").optional().isString(),
body("issuer").optional().isString(), body("issuer").optional().isString(),
body("cert").optional().isString(), body("cert").optional().isString(),
body("audience").optional().isString(),
validateRequest, validateRequest,
ssoController.updateSSOConfig ssoController.updateSSOConfig
); );
+1 -1
View File
@@ -66,7 +66,7 @@ class EELicenseService {
customRateLimits: true, customRateLimits: true,
customAlerts: true, customAlerts: true,
auditLogs: false, auditLogs: false,
samlSSO: false, samlSSO: true,
status: null, status: null,
trial_end: null, trial_end: null,
has_used_trial: true has_used_trial: true
+1 -1
View File
@@ -147,7 +147,7 @@ const initializePassport = async () => {
entryPoint: ssoConfig.entryPoint, entryPoint: ssoConfig.entryPoint,
issuer: ssoConfig.issuer, issuer: ssoConfig.issuer,
cert: ssoConfig.cert, cert: ssoConfig.cert,
audience: ssoConfig.audience audience: await getSiteURL()
}); });
req.ssoConfig = ssoConfig; req.ssoConfig = ssoConfig;
+4 -1
View File
@@ -3,7 +3,10 @@ title: "Azure SAML"
description: "Configure Azure SAML for Infisical SSO" description: "Configure Azure SAML for Infisical SSO"
--- ---
1. In the Azure Portal, navigate to the Azure Active Directory and select Enterprise applications. On this screen, select 1. In Infisical, head over to your organization Settings > Authentication > SAML SSO Configuration and select **Set up SAML SSO**.
Next, copy the **ACS URL** and **Entity ID** to use when configuring the Okta SAML 2.0 application.
2. In the Azure Portal, navigate to the Azure Active Directory and select Enterprise applications. On this screen, select
the **+ New application** button. the **+ New application** button.
TODO: insert image. TODO: insert image.
+34 -29
View File
@@ -1,72 +1,77 @@
--- ---
title: "Okta SAML" title: "Okta SAML"
description: "Configure Okta SAML for Infisical SSO" description: "Configure Okta SAML 2.0 for Infisical SSO"
--- ---
1. In the Okta Admin Portal, select Applications > Applications from the Prerequisites:
navigation. On the Applications screen, select the Create App Integration - Okta Developer Account with access to create custom application integrations.
1. In Infisical, head over to your organization Settings > Authentication > SAML SSO Configuration and select **Set up SAML SSO**.
Next, copy the **ACS URL** and **Entity ID** to use when configuring the Okta SAML 2.0 application.
![SAML Okta Infisical initial configuration](../../../images/sso-okta-0.png)
2. In the Okta Admin Portal, select Applications > Applications from the
navigation. On the Applications screen, select the **Create App Integration**
button. button.
![SAML Okta create app integration](../../../images/sso-okta-1.png) ![SAML Okta create app integration](../../../images/sso-okta-1.png)
2. In the Create a New Application Integration dialog, select the SAML 2.0 radio button: 3. In the Create a New Application Integration dialog, select the **SAML 2.0** radio button:
![SAML Okta create SAML 2.0 integration](../../../images/sso-okta-2.png) ![SAML Okta create SAML 2.0 integration](../../../images/sso-okta-2.png)
3. On the General Settings screen, give the application a unique, Infisical-specific name and select Next. 4. On the General Settings screen, give the application a unique name like Infisical and select **Next**.
4. On the Configure SAML screen, configure the following fields: ![SAML Okta create SAML 2.0 integration](../../../images/sso-okta-3.png)
- Single sign on URL: `https://app.infisical.com/api/v1/sso/saml2/:identifier`; we'll update the `:identifier` part later in step 6. 5. On the Configure SAML screen, set the **Single sign-on URL** to **ACS URL** and **Audience URI (SP Entity ID)** to
- Audience URI (SP Entity ID): `https://app.infisical.com` **Entity ID** from step 1.
![SAML Okta configure IdP fields](../../../images/sso-okta-3.png) ![SAML Okta configure IdP fields](../../../images/sso-okta-4.png)
<Note> <Note>
If you're self-hosting Infisical, then you will want to replace If you're self-hosting Infisical, then you will want to replace
`https://app.infisical.com` with your own domain. `https://app.infisical.com` with your own domain.
</Note> </Note>
4. Also on the Configure SAML screen, configure the Attribute Statements to map: 6. Also on the Configure SAML screen, configure the **Attribute Statements** to map:
- `id -> user.id`, - `id -> user.id`,
- `email -> user.email`, - `email -> user.email`,
- `firstName -> user.firstName` - `firstName -> user.firstName`
- `lastName -> user.lastName` - `lastName -> user.lastName`
![SAML Okta attribute statements](../../../images/sso-okta-4.png) ![SAML Okta attribute statements](../../../images/sso-okta-5.png)
Once configured, select the Next button to proceed to the Feedback screen and select Finish. Once configured, select the **Next** button to proceed to the Feedback screen and select **Finish**.
5. Get IdP values 7. Get IdP values
Once your application is created, select the Sign On tab for the app and select the View Setup Instructions button located on the right side of the screen: Once your application is created, select the **Sign On** tab for the app and select the **View Setup Instructions** button located on the right side of the screen:
Copy the Identity Provider Single Sign-On URL, the Identity Provider Issuer, and the X.509 Certificate to be pasted into your Infisical SAML SSO configuration details with the following map: ![SAML Okta view setup instructions](../../../images/sso-okta-6.png)
- `Audience -> Audience URI (SP Entity ID) from Okta` Copy the **Identity Provider Single Sign-On URL**, the **Identity Provider Issuer**, and the **X.509 Certificate** to use when finishing configuring the Okta SAML in Infisical.
- `Entrypoint -> Identity Provider Single Sign-On URL from Okta`
- `Issuer -> Identity Provider Issuer from Okta`
- `Certificate -> X.509 Certificate from Okta`
![SAML Okta IdP values](../../../images/saml-okta-5.png) ![SAML Okta IdP values](../../../images/sso-okta-7.png)
![SAML Okta paste values into Infisical](../../../images/sso-okta-6.png) Back in Infisical, set **Entrypoint** to **Identity Provider Single Sign-On URL**, **Issuer** to **Identity Provider Issuer**,
and **Certificate** to **X.509 Certificate** from above. Once you've done that, press **Add** to complete the required configuration.
6. Create the SSO configuration and copy your SSO identifier in Infisical; update `:identifier` from step 4 earlier to be this value. ![SAML Okta paste values into Infisical](../../../images/sso-okta-8.png)
![SAML Okta assignments](../../../images/sso-okta-7.png) 8. Finally, navigate to the **Assignments** tab and select **Assign**
7. Assignments
Finally, navigate to the Assignments tab and select the Assign button:
You can assign access to the application on a user-by-user basis using the Assign to People option, or in-bulk using the Assign to Groups option. You can assign access to the application on a user-by-user basis using the Assign to People option, or in-bulk using the Assign to Groups option.
![SAML Okta assignment](../../../images/sso-okta-8.png) ![SAML Okta assignment](../../../images/sso-okta-9.png)
At this point, you have configured everything you need within the context of the Okta Admin Portal. At this point, you have configured everything you need within the context of the Okta Admin Portal.
8. Return to Infisical and enable SAML SSO. 9. Return to Infisical and enable SAML SSO.
Enabling SAML SSO enforces all members in your organization to only be able to log into Infisical via Okta. Enabling SAML SSO enforces all members in your organization to only be able to log into Infisical via Okta.
![SAML Okta assignment](../../../images/sso-okta-10.png)
+1 -8
View File
@@ -13,11 +13,4 @@ description: "Log in to Infisical via SSO protocols"
You can configure your organization in Infisical to have members authenticate with the platform via protocols like [SAML 2.0](https://en.wikipedia.org/wiki/SAML_2.0). You can configure your organization in Infisical to have members authenticate with the platform via protocols like [SAML 2.0](https://en.wikipedia.org/wiki/SAML_2.0).
To note, configuring SSO retains the end-to-end encrypted architecture of Infisical because we decouple the **authentication** and **decryption** steps. In all login with SSO implementations, To note, configuring SSO retains the end-to-end encrypted architecture of Infisical because we decouple the **authentication** and **decryption** steps. In all login with SSO implementations,
your IdP cannot and will not have access to the decryption key needed to decrypt your secrets. your IdP cannot and will not have access to the decryption key needed to decrypt your secrets.
## Configuration
Head over to your organization Settings > Authentication > SAML SSO Configuration.
Next, press "Set up SAML SSO" in the SAML SSO and follow the instructions
below to configure SSO for your identity provider.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 423 KiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 KiB

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 598 KiB

After

Width:  |  Height:  |  Size: 316 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 443 KiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 KiB

After

Width:  |  Height:  |  Size: 598 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 KiB

After

Width:  |  Height:  |  Size: 443 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

+2 -1
View File
@@ -4,7 +4,8 @@ import SecurityClient from "@app/components/utilities/SecurityClient";
import { import {
getAuthToken, getAuthToken,
getMfaTempToken, getMfaTempToken,
getSignupTempToken} from "@app/reactQuery"; getSignupTempToken
} from "@app/reactQuery";
export const apiRequest = axios.create({ export const apiRequest = axios.create({
baseURL: "/", baseURL: "/",
+4 -10
View File
@@ -29,8 +29,7 @@ export const useCreateSSOConfig = () => {
isActive, isActive,
entryPoint, entryPoint,
issuer, issuer,
cert, cert
audience
}: { }: {
organizationId: string; organizationId: string;
authProvider: string; authProvider: string;
@@ -38,7 +37,6 @@ export const useCreateSSOConfig = () => {
entryPoint: string; entryPoint: string;
issuer: string; issuer: string;
cert: string; cert: string;
audience: string;
}) => { }) => {
const { data } = await apiRequest.post( const { data } = await apiRequest.post(
"/api/v1/sso/config", "/api/v1/sso/config",
@@ -48,8 +46,7 @@ export const useCreateSSOConfig = () => {
isActive, isActive,
entryPoint, entryPoint,
issuer, issuer,
cert, cert
audience
} }
); );
@@ -70,8 +67,7 @@ export const useUpdateSSOConfig = () => {
isActive, isActive,
entryPoint, entryPoint,
issuer, issuer,
cert, cert
audience
}: { }: {
organizationId: string; organizationId: string;
authProvider?: string; authProvider?: string;
@@ -79,7 +75,6 @@ export const useUpdateSSOConfig = () => {
entryPoint?: string; entryPoint?: string;
issuer?: string; issuer?: string;
cert?: string; cert?: string;
audience?: string;
}) => { }) => {
const { data } = await apiRequest.patch( const { data } = await apiRequest.patch(
"/api/v1/sso/config", "/api/v1/sso/config",
@@ -89,8 +84,7 @@ export const useUpdateSSOConfig = () => {
...(isActive !== undefined ? { isActive } : {}), ...(isActive !== undefined ? { isActive } : {}),
...(entryPoint !== undefined ? { entryPoint } : {}), ...(entryPoint !== undefined ? { entryPoint } : {}),
...(issuer !== undefined ? { issuer } : {}), ...(issuer !== undefined ? { issuer } : {}),
...(cert !== undefined ? { cert } : {}), ...(cert !== undefined ? { cert } : {})
...(audience !== undefined ? { audience } : {})
} }
); );
@@ -6,6 +6,7 @@ import { Button, Switch, UpgradePlanModal } from "@app/components/v2";
import { useOrganization, useSubscription } from "@app/context"; import { useOrganization, useSubscription } from "@app/context";
import { import {
useGetSSOConfig, useGetSSOConfig,
useCreateSSOConfig,
useUpdateSSOConfig useUpdateSSOConfig
} from "@app/hooks/api"; } from "@app/hooks/api";
import { usePopUp } from "@app/hooks/usePopUp"; import { usePopUp } from "@app/hooks/usePopUp";
@@ -27,6 +28,8 @@ export const OrgSSOSection = (): JSX.Element => {
"addSSO" "addSSO"
] as const); ] as const);
const { mutateAsync: createMutateAsync, isLoading: createIsLoading } = useCreateSSOConfig();
const handleSamlSSOToggle = async (value: boolean) => { const handleSamlSSOToggle = async (value: boolean) => {
try { try {
if (!currentOrg?._id) return; if (!currentOrg?._id) return;
@@ -49,6 +52,33 @@ export const OrgSSOSection = (): JSX.Element => {
} }
} }
const addSSOBtnClick = async () => {
try {
if (subscription?.samlSSO && currentOrg) {
if (!data) {
// case: SAML SSO is not configured
// -> initialize empty SAML SSO configuration
await createMutateAsync({
organizationId: currentOrg._id,
authProvider: "okta-saml",
isActive: false,
entryPoint: "",
issuer: "",
cert: ""
});
}
handlePopUpOpen("addSSO");
} else {
handlePopUpOpen("upgradePlan");
}
} catch (err) {
console.error(err);
}
}
console.log("getSSOConfig: ", data);
return ( return (
<div className="p-4 bg-mineshaft-900 mb-6 rounded-lg border border-mineshaft-600"> <div className="p-4 bg-mineshaft-900 mb-6 rounded-lg border border-mineshaft-600">
<div className="flex items-center mb-8"> <div className="flex items-center mb-8">
@@ -57,13 +87,7 @@ export const OrgSSOSection = (): JSX.Element => {
</h2> </h2>
{!isLoading && ( {!isLoading && (
<Button <Button
onClick={() => { onClick={addSSOBtnClick}
if (subscription?.samlSSO) {
handlePopUpOpen("addSSO");
} else {
handlePopUpOpen("upgradePlan");
}
}}
colorSchema="secondary" colorSchema="secondary"
leftIcon={<FontAwesomeIcon icon={faPlus} />} leftIcon={<FontAwesomeIcon icon={faPlus} />}
> >
@@ -71,39 +95,33 @@ export const OrgSSOSection = (): JSX.Element => {
</Button> </Button>
)} )}
</div> </div>
{!isLoading && data && ( {data && (
<> <div className="mb-4">
<div className="mb-4"> <Switch
<Switch id="enable-saml-sso"
id="enable-saml-sso" onCheckedChange={(value) => handleSamlSSOToggle(value)}
onCheckedChange={(value) => handleSamlSSOToggle(value)} isChecked={data ? data.isActive : false}
isChecked={data.isActive} >
> Enable SAML SSO
Enable SAML SSO </Switch>
</Switch> </div>
</div>
<div className="mb-4">
<h3 className="text-mineshaft-400 text-sm">SSO identifier</h3>
<p className="text-gray-400 text-md">{data._id}</p>
</div>
<div className="mb-4">
<h3 className="text-mineshaft-400 text-sm">Type</h3>
<p className="text-gray-400 text-md">{ssoAuthProviderMap[data.authProvider]}</p>
</div>
<div className="mb-4">
<h3 className="text-mineshaft-400 text-sm">Audience</h3>
<p className="text-gray-400 text-md">{data.audience}</p>
</div>
<div className="mb-4">
<h3 className="text-mineshaft-400 text-sm">Entrypoint</h3>
<p className="text-gray-400 text-md">{data.entryPoint}</p>
</div>
<div className="mb-4">
<h3 className="text-mineshaft-400 text-sm">Issuer</h3>
<p className="text-gray-400 text-md">{data.issuer}</p>
</div>
</>
)} )}
<div className="mb-4">
<h3 className="text-mineshaft-400 text-sm">SSO identifier</h3>
<p className="text-gray-400 text-md">{(data && data._id !== "") ? data._id : "-"}</p>
</div>
<div className="mb-4">
<h3 className="text-mineshaft-400 text-sm">Type</h3>
<p className="text-gray-400 text-md">{(data && data.authProvider !== "") ? ssoAuthProviderMap[data.authProvider] : "-"}</p>
</div>
<div className="mb-4">
<h3 className="text-mineshaft-400 text-sm">Entrypoint</h3>
<p className="text-gray-400 text-md">{(data && data.entryPoint !== "") ? data.entryPoint : "-"}</p>
</div>
<div className="mb-4">
<h3 className="text-mineshaft-400 text-sm">Issuer</h3>
<p className="text-gray-400 text-md">{(data && data.issuer !== "") ? data.issuer : "-"}</p>
</div>
<SSOModal <SSOModal
popUp={popUp} popUp={popUp}
handlePopUpClose={handlePopUpClose} handlePopUpClose={handlePopUpClose}
@@ -2,7 +2,6 @@ import { useEffect } from "react";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup"; import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup"; import * as yup from "yup";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
import { import {
Button, Button,
@@ -29,8 +28,7 @@ const schema = yup.object({
authProvider: yup.string().required("SSO Type is required"), authProvider: yup.string().required("SSO Type is required"),
entryPoint: yup.string().required("IDP entrypoint is required"), entryPoint: yup.string().required("IDP entrypoint is required"),
issuer: yup.string().required("Issuer string is required"), issuer: yup.string().required("Issuer string is required"),
cert: yup.string().required("IDP's public signing certificate is required"), cert: yup.string().required("IDP's public signing certificate is required")
audience: yup.string().required("Expected SAML response audience is required"),
}).required(); }).required();
export type AddSSOFormData = yup.InferType<typeof schema>; export type AddSSOFormData = yup.InferType<typeof schema>;
@@ -70,8 +68,7 @@ export const SSOModal = ({
authProvider: data?.authProvider ?? "", authProvider: data?.authProvider ?? "",
entryPoint: data?.entryPoint ?? "", entryPoint: data?.entryPoint ?? "",
issuer: data?.issuer ?? "", issuer: data?.issuer ?? "",
cert: data?.cert ?? "", cert: data?.cert ?? ""
audience: data?.audience ?? ""
}); });
} }
}, [data]); }, [data]);
@@ -80,8 +77,7 @@ export const SSOModal = ({
authProvider, authProvider,
entryPoint, entryPoint,
issuer, issuer,
cert, cert
audience
}: AddSSOFormData) => { }: AddSSOFormData) => {
try { try {
if (!currentOrg) return; if (!currentOrg) return;
@@ -93,8 +89,7 @@ export const SSOModal = ({
isActive: false, isActive: false,
entryPoint, entryPoint,
issuer, issuer,
cert, cert
audience
}); });
} else { } else {
await updateMutateAsync({ await updateMutateAsync({
@@ -103,8 +98,7 @@ export const SSOModal = ({
isActive: false, isActive: false,
entryPoint, entryPoint,
issuer, issuer,
cert, cert
audience
}); });
} }
@@ -160,24 +154,16 @@ export const SSOModal = ({
</FormControl> </FormControl>
)} )}
/> />
{authProvider && authProvider === "okta-saml" && ( {authProvider && authProvider === "okta-saml" && data && (
<> <>
<Controller <div className="mb-4">
control={control} <h3 className="text-mineshaft-400 text-sm">ACS URL</h3>
name="audience" <p className="text-gray-400 text-md break-all">{`${window.origin}/api/v1/sso/saml2/${data._id}`}</p>
render={({ field, fieldState: { error } }) => ( </div>
<FormControl <div className="mb-4">
label="Audience" <h3 className="text-mineshaft-400 text-sm">Entity ID</h3>
errorText={error?.message} <p className="text-gray-400 text-md">{window.origin}</p>
isError={Boolean(error)} </div>
>
<Input
{...field}
placeholder="https://your-domain.com"
/>
</FormControl>
)}
/>
<Controller <Controller
control={control} control={control}
name="entryPoint" name="entryPoint"