feat(sso): allow to use OIDC and SAML (#7246)

## What it does
### Backend
- [x] Add a mutation to create OIDC and SAML configuration
- [x] Add a mutation to delete an SSO config
- [x] Add a feature flag to toggle SSO
- [x] Add a mutation to activate/deactivate an SSO config
- [x] Add a mutation to delete an SSO config
- [x] Add strategy to use OIDC or SAML
- [ ] Improve error management

### Frontend
- [x] Add section "security" in settings
- [x] Add page to list SSO configurations
- [x] Add page and forms to create OIDC or SAML configuration
- [x] Add field to "connect with SSO" in the signin/signup process
- [x] Trigger auth when a user switch to a workspace with SSO enable
- [x] Add an option on the security page to activate/deactivate the
global invitation link
- [ ] Add new Icons for SSO Identity Providers (okta, Auth0, Azure,
Microsoft)

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Antoine Moreaux
2024-10-21 20:07:08 +02:00
committed by GitHub
parent 11c3f1c399
commit 0f0a7966b1
132 changed files with 5245 additions and 306 deletions

View File

@ -0,0 +1,68 @@
/* @license Enterprise */
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import {
FindAvailableSsoIdentityProvidersMutationVariables,
GetAuthorizationUrlMutationVariables,
useFindAvailableSsoIdentityProvidersMutation,
useGetAuthorizationUrlMutation,
} from '~/generated/graphql';
import { isDefined } from '~/utils/isDefined';
export const useSSO = () => {
const { enqueueSnackBar } = useSnackBar();
const [findAvailableSSOProviderByEmailMutation] =
useFindAvailableSsoIdentityProvidersMutation();
const [getAuthorizationUrlMutation] = useGetAuthorizationUrlMutation();
const findAvailableSSOProviderByEmail = async ({
email,
}: FindAvailableSsoIdentityProvidersMutationVariables['input']) => {
return await findAvailableSSOProviderByEmailMutation({
variables: {
input: { email },
},
});
};
const getAuthorizationUrlForSSO = async ({
identityProviderId,
}: GetAuthorizationUrlMutationVariables['input']) => {
return await getAuthorizationUrlMutation({
variables: {
input: { identityProviderId },
},
});
};
const redirectToSSOLoginPage = async (identityProviderId: string) => {
const authorizationUrlForSSOResult = await getAuthorizationUrlForSSO({
identityProviderId,
});
if (
isDefined(authorizationUrlForSSOResult.errors) ||
!authorizationUrlForSSOResult.data ||
!authorizationUrlForSSOResult.data?.getAuthorizationUrl.authorizationURL
) {
return enqueueSnackBar(
authorizationUrlForSSOResult.errors?.[0]?.message ?? 'Unknown error',
{
variant: SnackBarVariant.Error,
},
);
}
window.location.href =
authorizationUrlForSSOResult.data?.getAuthorizationUrl.authorizationURL;
return;
};
return {
redirectToSSOLoginPage,
getAuthorizationUrlForSSO,
findAvailableSSOProviderByEmail,
};
};