diff --git a/Dockerfile b/Dockerfile
index 967545e24..f5a671fa6 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-ARG NODEJS_IMAGE=node:18.15.0-alpine3.17
+ARG NODEJS_IMAGE=node:18.16.1-alpine3.18
FROM --platform=$BUILDPLATFORM $NODEJS_IMAGE AS base
# Install dependencies only when needed
diff --git a/README.md b/README.md
index 7669aeef1..6577daf84 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
# SAML Jackson: Enterprise SSO made simple
+
@@ -28,7 +29,13 @@ Jackson implements the SAML login flow as an OAuth 2.0 or OpenID Connect flow, a
Try our hosted demo showcasing the SAML SP login flow [here](https://saml-demo.boxyhq.com), no SAML configuration required thanks to our [Mock SAML](https://mocksaml.com) service.
-You can also try our hosted demo showcasing the SAML IdP login flow [here](https://mocksaml.com/saml/login).
+## Videos
+- SSO/OIDC Tutorial [SAML Jackson Enterprise SSO](https://www.youtube.com/watch?v=nvsD4-GQw4A)
+- SAML single sign-on login [demo](https://www.youtube.com/watch?v=VBUznQwoEWU)
+
+## Demo
+- SAML IdP login flow showcasing self hosted [Mock SAML](https://mocksaml.com/saml/login)
+- SAML [demo flow](https://saml-demo.boxyhq.com/)
## Documentation
diff --git a/components/connection/EditConnection.tsx b/components/connection/EditConnection.tsx
index c498e9e1d..4a7cec16e 100644
--- a/components/connection/EditConnection.tsx
+++ b/components/connection/EditConnection.tsx
@@ -103,14 +103,16 @@ const EditConnection = ({ connection, setupLinkToken, isSettingsView = false }:
const [delModalVisible, setDelModalVisible] = useState(false);
const toggleDelConfirm = () => setDelModalVisible(!delModalVisible);
const deleteConnection = async () => {
+ const queryParams = new URLSearchParams({
+ clientID: connection.clientID,
+ clientSecret: connection.clientSecret,
+ });
const res = await fetch(
- setupLinkToken ? `/api/setup/${setupLinkToken}/sso-connection` : '/api/admin/connections',
+ setupLinkToken
+ ? `/api/setup/${setupLinkToken}/sso-connection?${queryParams}`
+ : `/api/admin/connections?${queryParams}`,
{
method: 'DELETE',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ clientID: connection?.clientID, clientSecret: connection?.clientSecret }),
}
);
diff --git a/components/dsync/CreateDirectory.tsx b/components/dsync/CreateDirectory.tsx
index c084e77c3..f9444a017 100644
--- a/components/dsync/CreateDirectory.tsx
+++ b/components/dsync/CreateDirectory.tsx
@@ -1,6 +1,6 @@
import { useTranslation } from 'next-i18next';
import { useRouter } from 'next/router';
-import React, { useEffect, useState } from 'react';
+import React, { useState } from 'react';
import { ApiResponse } from 'types';
import { errorToast, successToast } from '@components/Toaster';
import type { Directory } from '@boxyhq/saml-jackson';
@@ -13,28 +13,32 @@ interface CreateDirectoryProps {
defaultWebhookEndpoint: string | undefined;
}
+type UnSavedDirectory = Omit & {
+ webhook_url: string;
+ webhook_secret: string;
+};
+
+const defaultDirectory: UnSavedDirectory = {
+ name: '',
+ tenant: '',
+ product: '',
+ webhook_url: '',
+ webhook_secret: '',
+ type: 'azure-scim-v2',
+ google_domain: '',
+};
+
const CreateDirectory = ({ setupLinkToken, defaultWebhookEndpoint }: CreateDirectoryProps) => {
const { t } = useTranslation('common');
const router = useRouter();
const { providers } = useDirectoryProviders(setupLinkToken);
const [loading, setLoading] = useState(false);
- const [directory, setDirectory] = useState({
- name: '',
- tenant: '',
- product: '',
- webhook_url: defaultWebhookEndpoint,
- webhook_secret: '',
- type: '',
+ const [showDomain, setShowDomain] = useState(false);
+ const [directory, setDirectory] = useState({
+ ...defaultDirectory,
+ webhook_url: defaultWebhookEndpoint || '',
});
- useEffect(() => {
- if (providers && Object.keys(providers).length > 0) {
- setDirectory((directory) => {
- return { ...directory, type: Object.keys(providers)[0] };
- });
- }
- }, [providers]);
-
const onSubmit = async (event: React.FormEvent) => {
event.preventDefault();
@@ -78,6 +82,11 @@ const CreateDirectory = ({ setupLinkToken, defaultWebhookEndpoint }: CreateDirec
...directory,
[target.id]: target.value,
});
+
+ // Ask for domain if google is selected
+ if (target.id === 'type') {
+ target.value === 'google' ? setShowDomain(true) : setShowDomain(false);
+ }
};
const backUrl = setupLinkToken ? `/setup/${setupLinkToken}/directory-sync` : '/admin/directory-sync';
@@ -116,6 +125,22 @@ const CreateDirectory = ({ setupLinkToken, defaultWebhookEndpoint }: CreateDirec
})}
+ {showDomain && (
+
+
+
+
+ )}
{!setupLinkToken && (
<>
diff --git a/components/dsync/DirectoryInfo.tsx b/components/dsync/DirectoryInfo.tsx
index 7a9fc5d3b..8d3815e4f 100644
--- a/components/dsync/DirectoryInfo.tsx
+++ b/components/dsync/DirectoryInfo.tsx
@@ -6,6 +6,7 @@ import React from 'react';
import useDirectory from '@lib/ui/hooks/useDirectory';
import Loading from '@components/Loading';
import { errorToast } from '@components/Toaster';
+import { dsyncGoogleAuthURL } from '@lib/env';
const DirectoryInfo = ({ directoryId, setupLinkToken }: { directoryId: string; setupLinkToken?: string }) => {
const { t } = useTranslation('common');
@@ -71,14 +72,24 @@ const DirectoryInfo = ({ directoryId, setupLinkToken }: { directoryId: string; s
)}
-
-
-
+ {directory.scim.endpoint && directory.scim.secret && (
+
-
-
+ )}
+ {directory.type === 'google' && (
+
+
-
+ )}
>
);
diff --git a/components/dsync/EditDirectory.tsx b/components/dsync/EditDirectory.tsx
index 111484069..5f2f231e2 100644
--- a/components/dsync/EditDirectory.tsx
+++ b/components/dsync/EditDirectory.tsx
@@ -11,7 +11,7 @@ import useDirectory from '@lib/ui/hooks/useDirectory';
import { ToggleConnectionStatus } from './ToggleConnectionStatus';
import { DeleteDirectory } from './DeleteDirectory';
-type FormState = Pick
;
+type FormState = Pick;
const defaultFormState: FormState = {
name: '',
@@ -20,6 +20,7 @@ const defaultFormState: FormState = {
endpoint: '',
secret: '',
},
+ google_domain: '',
};
const EditDirectory = ({ directoryId, setupLinkToken }: { directoryId: string; setupLinkToken?: string }) => {
@@ -39,6 +40,7 @@ const EditDirectory = ({ directoryId, setupLinkToken }: { directoryId: string; s
endpoint: directory.webhook?.endpoint,
secret: directory.webhook?.secret,
},
+ google_domain: directory.google_domain,
});
}
}, [directory]);
@@ -131,6 +133,20 @@ const EditDirectory = ({ directoryId, setupLinkToken }: { directoryId: string; s
value={directoryUpdated.name}
/>
+ {directory.type === 'google' && (
+
+
+
+
+ )}