Integrated login with Gitlab

This commit is contained in:
Andrew Atimapre
2023-09-24 15:21:23 +01:00
parent f342c345b7
commit 255705501f
10 changed files with 383 additions and 304 deletions
+20
View File
@@ -46,6 +46,7 @@
"nodemailer": "^6.8.0", "nodemailer": "^6.8.0",
"passport": "^0.6.0", "passport": "^0.6.0",
"passport-github": "^1.1.0", "passport-github": "^1.1.0",
"passport-gitlab2": "^5.0.0",
"passport-google-oauth20": "^2.0.0", "passport-google-oauth20": "^2.0.0",
"posthog-node": "^2.6.0", "posthog-node": "^2.6.0",
"probot": "^12.3.1", "probot": "^12.3.1",
@@ -13698,6 +13699,17 @@
"node": ">= 0.4.0" "node": ">= 0.4.0"
} }
}, },
"node_modules/passport-gitlab2": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/passport-gitlab2/-/passport-gitlab2-5.0.0.tgz",
"integrity": "sha512-cXQMgM6JQx9wHVh7JLH30D8fplfwjsDwRz+zS0pqC8JS+4bNmc1J04NGp5g2M4yfwylH9kQRrMN98GxMw7q7cg==",
"dependencies": {
"passport-oauth2": "^1.4.0"
},
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/passport-google-oauth20": { "node_modules/passport-google-oauth20": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz",
@@ -27074,6 +27086,14 @@
"passport-oauth2": "1.x.x" "passport-oauth2": "1.x.x"
} }
}, },
"passport-gitlab2": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/passport-gitlab2/-/passport-gitlab2-5.0.0.tgz",
"integrity": "sha512-cXQMgM6JQx9wHVh7JLH30D8fplfwjsDwRz+zS0pqC8JS+4bNmc1J04NGp5g2M4yfwylH9kQRrMN98GxMw7q7cg==",
"requires": {
"passport-oauth2": "^1.4.0"
}
},
"passport-google-oauth20": { "passport-google-oauth20": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz",
+1
View File
@@ -37,6 +37,7 @@
"nodemailer": "^6.8.0", "nodemailer": "^6.8.0",
"passport": "^0.6.0", "passport": "^0.6.0",
"passport-github": "^1.1.0", "passport-github": "^1.1.0",
"passport-gitlab2": "^5.0.0",
"passport-google-oauth20": "^2.0.0", "passport-google-oauth20": "^2.0.0",
"posthog-node": "^2.6.0", "posthog-node": "^2.6.0",
"probot": "^12.3.1", "probot": "^12.3.1",
+2
View File
@@ -52,6 +52,8 @@ export const getClientIdGoogleLogin = async () => (await client.getSecret("CLIEN
export const getClientSecretGoogleLogin = async () => (await client.getSecret("CLIENT_SECRET_GOOGLE_LOGIN")).secretValue; export const getClientSecretGoogleLogin = async () => (await client.getSecret("CLIENT_SECRET_GOOGLE_LOGIN")).secretValue;
export const getClientIdGitHubLogin = async () => (await client.getSecret("CLIENT_ID_GITHUB_LOGIN")).secretValue; export const getClientIdGitHubLogin = async () => (await client.getSecret("CLIENT_ID_GITHUB_LOGIN")).secretValue;
export const getClientSecretGitHubLogin = async () => (await client.getSecret("CLIENT_SECRET_GITHUB_LOGIN")).secretValue; export const getClientSecretGitHubLogin = async () => (await client.getSecret("CLIENT_SECRET_GITHUB_LOGIN")).secretValue;
export const getClientIdGitLabLogin = async () => (await client.getSecret("CLIENT_ID_GITLAB_LOGIN")).secretValue;
export const getClientSecretGitLabLogin = async () => (await client.getSecret("CLIENT_SECRET_GITLAB_LOGIN")).secretValue;
export const getPostHogHost = async () => (await client.getSecret("POSTHOG_HOST")).secretValue || "https://app.posthog.com"; export const getPostHogHost = async () => (await client.getSecret("POSTHOG_HOST")).secretValue || "https://app.posthog.com";
export const getPostHogProjectApiKey = async () => (await client.getSecret("POSTHOG_PROJECT_API_KEY")).secretValue || "phc_nSin8j5q2zdhpFDI1ETmFNUIuTG4DwKVyIigrY10XiE"; export const getPostHogProjectApiKey = async () => (await client.getSecret("POSTHOG_PROJECT_API_KEY")).secretValue || "phc_nSin8j5q2zdhpFDI1ETmFNUIuTG4DwKVyIigrY10XiE";
+23
View File
@@ -65,6 +65,29 @@ router.get(
ssoController.redirectSSO ssoController.redirectSSO
); );
router.get(
"/redirect/gitlab",
authLimiter,
(req, res, next) => {
passport.authenticate("gitlab", {
session: false,
...(req.query.callback_port ? {
state: req.query.callback_port as string
} : {})
})(req, res, next);
}
)
router.get(
"/gitlab",
authLimiter,
passport.authenticate("gitlab", {
failureRedirect: "/login/provider/error",
session: false
}),
ssoController.redirectSSO
)
router.get( router.get(
"/redirect/saml2/:ssoIdentifier", "/redirect/saml2/:ssoIdentifier",
authLimiter, authLimiter,
+1
View File
@@ -4,6 +4,7 @@ export enum AuthMethod {
EMAIL = "email", EMAIL = "email",
GOOGLE = "google", GOOGLE = "google",
GITHUB = "github", GITHUB = "github",
GITLAB = "gitlab",
OKTA_SAML = "okta-saml", OKTA_SAML = "okta-saml",
AZURE_SAML = "azure-saml", AZURE_SAML = "azure-saml",
JUMPCLOUD_SAML = "jumpcloud-saml", JUMPCLOUD_SAML = "jumpcloud-saml",
+2 -1
View File
@@ -51,7 +51,8 @@ router.put(
return authMethods.every(provider => [ return authMethods.every(provider => [
AuthMethod.EMAIL, AuthMethod.EMAIL,
AuthMethod.GOOGLE, AuthMethod.GOOGLE,
AuthMethod.GITHUB AuthMethod.GITHUB,
AuthMethod.GITLAB
].includes(provider)) ].includes(provider))
}), }),
validateRequest, validateRequest,
@@ -155,6 +155,12 @@ Other environment variables are listed below to increase the functionality of yo
<ParamField query="CLIENT_SECRET_GITHUB_LOGIN" type="string" default="none" optional> <ParamField query="CLIENT_SECRET_GITHUB_LOGIN" type="string" default="none" optional>
OAuth2 client secret for GitHub login OAuth2 client secret for GitHub login
</ParamField> </ParamField>
<ParamField query="CLIENT_ID_GITLAB_LOGIN" type="string" default="none" optional>
OAuth2 client ID for GitLab login
</ParamField>
<ParamField query="CLIENT_SECRET_GITLAB_LOGIN" type="string" default="none" optional>
OAuth2 client secret for GitLab login
</ParamField>
</Tab> </Tab>
<Tab title="Others"> <Tab title="Others">
#### JWT #### JWT
+1
View File
@@ -4,6 +4,7 @@ export enum AuthMethod {
EMAIL = "email", EMAIL = "email",
GOOGLE = "google", GOOGLE = "google",
GITHUB = "github", GITHUB = "github",
GITLAB = "gitlab",
OKTA_SAML = "okta-saml", OKTA_SAML = "okta-saml",
AZURE_SAML = "azure-saml", AZURE_SAML = "azure-saml",
JUMPCLOUD_SAML = "jumpcloud-saml" JUMPCLOUD_SAML = "jumpcloud-saml"
@@ -2,10 +2,10 @@ import { FormEvent, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { faGithub,faGoogle } from "@fortawesome/free-brands-svg-icons"; import { faGithub, faGitlab, faGoogle } from "@fortawesome/free-brands-svg-icons";
import { faLock } from "@fortawesome/free-solid-svg-icons"; import { faLock } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import axios from "axios" import axios from "axios";
import Error from "@app/components/basic/Error"; import Error from "@app/components/basic/Error";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
@@ -21,15 +21,9 @@ type Props = {
setEmail: (email: string) => void; setEmail: (email: string) => void;
password: string; password: string;
setPassword: (email: string) => void; setPassword: (email: string) => void;
} };
export const InitialStep = ({ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }: Props) => {
setStep,
email,
setEmail,
password,
setPassword
}: Props) => {
const router = useRouter(); const router = useRouter();
const { createNotification } = useNotificationContext(); const { createNotification } = useNotificationContext();
const { t } = useTranslation(); const { t } = useTranslation();
@@ -39,7 +33,7 @@ export const InitialStep = ({
const queryParams = new URLSearchParams(window.location.search); const queryParams = new URLSearchParams(window.location.search);
const handleLogin = async (e: FormEvent<HTMLFormElement>) => { const handleLogin = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault() e.preventDefault();
try { try {
if (!email || !password) { if (!email || !password) {
return; return;
@@ -47,16 +41,15 @@ export const InitialStep = ({
setIsLoading(true); setIsLoading(true);
if (queryParams && queryParams.get("callback_port")) { if (queryParams && queryParams.get("callback_port")) {
const callbackPort = queryParams.get("callback_port") const callbackPort = queryParams.get("callback_port");
// attemptCliLogin // attemptCliLogin
const isCliLoginSuccessful = await attemptCliLogin({ const isCliLoginSuccessful = await attemptCliLogin({
email: email.toLowerCase(), email: email.toLowerCase(),
password, password
}) });
if (isCliLoginSuccessful && isCliLoginSuccessful.success) { if (isCliLoginSuccessful && isCliLoginSuccessful.success) {
if (isCliLoginSuccessful.mfaEnabled) { if (isCliLoginSuccessful.mfaEnabled) {
// case: login requires MFA step // case: login requires MFA step
setStep(1); setStep(1);
@@ -64,22 +57,21 @@ export const InitialStep = ({
return; return;
} }
// case: login was successful // case: login was successful
const cliUrl = `http://localhost:${callbackPort}` const cliUrl = `http://localhost:${callbackPort}`;
// send request to server endpoint // send request to server endpoint
const instance = axios.create() const instance = axios.create();
await instance.post(cliUrl, { ...isCliLoginSuccessful.loginResponse }) await instance.post(cliUrl, { ...isCliLoginSuccessful.loginResponse });
// cli page // cli page
router.push("/cli-redirect"); router.push("/cli-redirect");
// on success, router.push to cli Login Successful page // on success, router.push to cli Login Successful page
} }
} else { } else {
const isLoginSuccessful = await attemptLogin({ const isLoginSuccessful = await attemptLogin({
email: email.toLowerCase(), email: email.toLowerCase(),
password, password
}); });
if (isLoginSuccessful && isLoginSuccessful.success) { if (isLoginSuccessful && isLoginSuccessful.success) {
// case: login was successful // case: login was successful
@@ -101,8 +93,6 @@ export const InitialStep = ({
router.push(`/org/${userOrg}/overview`); router.push(`/org/${userOrg}/overview`);
} }
} }
} catch (err) { } catch (err) {
setLoginError(true); setLoginError(true);
createNotification({ createNotification({
@@ -112,45 +102,73 @@ export const InitialStep = ({
} }
setIsLoading(false); setIsLoading(false);
} };
return ( return (
<form onSubmit={handleLogin} className='flex flex-col mx-auto w-full justify-center items-center'> <form
<h1 className='text-xl font-medium text-transparent bg-clip-text bg-gradient-to-b from-white to-bunker-200 text-center mb-8' >Login to Infisical</h1> onSubmit={handleLogin}
<div className='lg:w-1/6 w-1/4 min-w-[21.2rem] md:min-w-[20.1rem] text-center rounded-md mt-4'> className="mx-auto flex w-full flex-col items-center justify-center"
>
<h1 className="mb-8 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
Login to Infisical
</h1>
<div className="mt-4 w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
<Button <Button
colorSchema="primary" colorSchema="primary"
variant="outline_bg" variant="outline_bg"
onClick={() => { onClick={() => {
const callbackPort = queryParams.get("callback_port"); const callbackPort = queryParams.get("callback_port");
window.open(`/api/v1/sso/redirect/google${callbackPort ? `?callback_port=${callbackPort}` : ""}`); window.open(
`/api/v1/sso/redirect/google${callbackPort ? `?callback_port=${callbackPort}` : ""}`
);
window.close(); window.close();
}} }}
leftIcon={<FontAwesomeIcon icon={faGoogle} className="mr-2" />} leftIcon={<FontAwesomeIcon icon={faGoogle} className="mr-2" />}
className="h-11 w-full mx-0" className="mx-0 h-11 w-full"
> >
{t("login.continue-with-google")} {t("login.continue-with-google")}
</Button> </Button>
</div> </div>
<div className='lg:w-1/6 w-1/4 min-w-[21.2rem] md:min-w-[20.1rem] text-center rounded-md mt-4'> <div className="mt-4 w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
<Button <Button
colorSchema="primary" colorSchema="primary"
variant="outline_bg" variant="outline_bg"
onClick={() => { onClick={() => {
const callbackPort = queryParams.get("callback_port"); const callbackPort = queryParams.get("callback_port");
window.open(`/api/v1/sso/redirect/github${callbackPort ? `?callback_port=${callbackPort}` : ""}`); window.open(
`/api/v1/sso/redirect/github${callbackPort ? `?callback_port=${callbackPort}` : ""}`
);
window.close(); window.close();
}} }}
leftIcon={<FontAwesomeIcon icon={faGithub} className="mr-2" />} leftIcon={<FontAwesomeIcon icon={faGithub} className="mr-2" />}
className="h-11 w-full mx-0" className="mx-0 h-11 w-full"
> >
Continue with GitHub Continue with GitHub
</Button> </Button>
</div> </div>
<div className='lg:w-1/6 w-1/4 min-w-[21.2rem] md:min-w-[20.1rem] text-center rounded-md mt-4'> <div className="mt-4 w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
<Button
colorSchema="primary"
variant="outline_bg"
onClick={() => {
const callbackPort = queryParams.get("callback_port");
window.open(
`/api/v1/sso/redirect/gitlab${callbackPort ? `?callback_port=${callbackPort}` : ""}`
);
window.close();
}}
leftIcon={<FontAwesomeIcon icon={faGitlab} className="mr-2" />}
className="mx-0 h-11 w-full"
>
Continue with GitLab
</Button>
</div>
<div className="mt-4 w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
<Button <Button
colorSchema="primary" colorSchema="primary"
variant="outline_bg" variant="outline_bg"
@@ -158,17 +176,17 @@ export const InitialStep = ({
setStep(2); setStep(2);
}} }}
leftIcon={<FontAwesomeIcon icon={faLock} className="mr-2" />} leftIcon={<FontAwesomeIcon icon={faLock} className="mr-2" />}
className="h-11 w-full mx-0" className="mx-0 h-11 w-full"
> >
Continue with SSO Continue with SSO
</Button> </Button>
</div> </div>
<div className='lg:w-1/6 w-1/4 min-w-[20rem] flex flex-row items-center my-4 py-2'> <div className="my-4 flex w-1/4 min-w-[20rem] flex-row items-center py-2 lg:w-1/6">
<div className='w-full border-t border-mineshaft-400/60' /> <div className="w-full border-t border-mineshaft-400/60" />
<span className="mx-2 text-mineshaft-200 text-xs">or</span> <span className="mx-2 text-xs text-mineshaft-200">or</span>
<div className='w-full border-t border-mineshaft-400/60' /> <div className="w-full border-t border-mineshaft-400/60" />
</div> </div>
<div className='lg:w-1/6 w-1/4 min-w-[21.2rem] md:min-w-[20.1rem] text-center rounded-md'> <div className="w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
<Input <Input
value={email} value={email}
onChange={(e) => setEmail(e.target.value)} onChange={(e) => setEmail(e.target.value)}
@@ -179,7 +197,7 @@ export const InitialStep = ({
className="h-11" className="h-11"
/> />
</div> </div>
<div className='lg:w-1/6 w-1/4 min-w-[21.2rem] md:min-w-[20.1rem] text-center rounded-md mt-4'> <div className="mt-4 w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
<Input <Input
value={password} value={password}
onChange={(e) => setPassword(e.target.value)} onChange={(e) => setPassword(e.target.value)}
@@ -188,36 +206,44 @@ export const InitialStep = ({
isRequired isRequired
autoComplete="current-password" autoComplete="current-password"
id="current-password" id="current-password"
className="h-11 select:-webkit-autofill:focus" className="select:-webkit-autofill:focus h-11"
/> />
</div> </div>
<div className='lg:w-1/6 w-1/4 min-w-[21.2rem] md:min-w-[20.1rem] text-center rounded-md mt-5'> <div className="mt-5 w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
<Button <Button
type="submit" type="submit"
size="sm" size="sm"
isFullWidth isFullWidth
className='h-11' className="h-11"
colorSchema="primary" colorSchema="primary"
variant="solid" variant="solid"
isLoading={isLoading} isLoading={isLoading}
> Continue with Email </Button> >
{" "}
Continue with Email{" "}
</Button>
</div> </div>
{!isLoading && loginError && <Error text={t("login.error-login") ?? ""} />} {!isLoading && loginError && <Error text={t("login.error-login") ?? ""} />}
{ {!serverDetails?.inviteOnlySignup ? (
!serverDetails?.inviteOnlySignup ? <div className="mt-6 flex flex-row text-sm text-bunker-400">
<div className="mt-6 text-bunker-400 text-sm flex flex-row">
<span className="mr-1">Don&apos;t have an acount yet?</span> <span className="mr-1">Don&apos;t have an acount yet?</span>
<Link href="/signup"> <Link href="/signup">
<span className='hover:underline hover:underline-offset-4 hover:decoration-primary-700 hover:text-bunker-200 duration-200 cursor-pointer'>{t("login.create-account")}</span> <span className="cursor-pointer duration-200 hover:text-bunker-200 hover:underline hover:decoration-primary-700 hover:underline-offset-4">
{t("login.create-account")}
</span>
</Link> </Link>
</div> : <div /> </div>
} ) : (
<div className="text-bunker-400 text-sm flex flex-row"> <div />
)}
<div className="flex flex-row text-sm text-bunker-400">
<span className="mr-1">Forgot password?</span> <span className="mr-1">Forgot password?</span>
<Link href="/verify-email"> <Link href="/verify-email">
<span className='hover:underline hover:underline-offset-4 hover:decoration-primary-700 hover:text-bunker-200 duration-200 cursor-pointer'>Recover your account</span> <span className="cursor-pointer duration-200 hover:text-bunker-200 hover:underline hover:decoration-primary-700 hover:underline-offset-4">
Recover your account
</span>
</Link> </Link>
</div> </div>
</form> </form>
); );
} };
@@ -1,6 +1,6 @@
import { useEffect } from "react"; import { useEffect } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { faGithub, faGoogle, IconDefinition } from "@fortawesome/free-brands-svg-icons"; import { faGithub, faGitlab, faGoogle, IconDefinition } from "@fortawesome/free-brands-svg-icons";
import { faEnvelope } from "@fortawesome/free-regular-svg-icons"; import { faEnvelope } from "@fortawesome/free-regular-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { yupResolver } from "@hookform/resolvers/yup"; import { yupResolver } from "@hookform/resolvers/yup";
@@ -10,20 +10,19 @@ import { useNotificationContext } from "@app/components/context/Notifications/No
import { Switch } from "@app/components/v2"; import { Switch } from "@app/components/v2";
import { useUser } from "@app/context"; import { useUser } from "@app/context";
import { useUpdateUserAuthMethods } from "@app/hooks/api"; import { useUpdateUserAuthMethods } from "@app/hooks/api";
import { import { AuthMethod } from "@app/hooks/api/users/types";
AuthMethod
} from "@app/hooks/api/users/types";
interface AuthMethodOption { interface AuthMethodOption {
label: string, label: string;
value: AuthMethod, value: AuthMethod;
icon: IconDefinition; icon: IconDefinition;
} }
const authMethodOpts: AuthMethodOption[] = [ const authMethodOpts: AuthMethodOption[] = [
{ label: "Email", value: AuthMethod.EMAIL, icon: faEnvelope }, { label: "Email", value: AuthMethod.EMAIL, icon: faEnvelope },
{ label: "Google", value: AuthMethod.GOOGLE, icon: faGoogle }, { label: "Google", value: AuthMethod.GOOGLE, icon: faGoogle },
{ label: "GitHub", value: AuthMethod.GITHUB, icon: faGithub } { label: "GitHub", value: AuthMethod.GITHUB, icon: faGithub },
{ label: "GitLab", value: AuthMethod.GITLAB, icon: faGitlab }
]; ];
const samlProviders = [AuthMethod.OKTA_SAML, AuthMethod.JUMPCLOUD_SAML, AuthMethod.AZURE_SAML]; const samlProviders = [AuthMethod.OKTA_SAML, AuthMethod.JUMPCLOUD_SAML, AuthMethod.AZURE_SAML];
@@ -39,13 +38,9 @@ export const AuthMethodSection = () => {
const { user } = useUser(); const { user } = useUser();
const { mutateAsync } = useUpdateUserAuthMethods(); const { mutateAsync } = useUpdateUserAuthMethods();
const { const { reset, setValue, watch } = useForm<FormData>({
reset,
setValue,
watch,
} = useForm<FormData>({
defaultValues: { defaultValues: {
authMethods: user.authMethods, authMethods: user.authMethods
}, },
resolver: yupResolver(schema) resolver: yupResolver(schema)
}); });
@@ -55,14 +50,15 @@ export const AuthMethodSection = () => {
useEffect(() => { useEffect(() => {
if (user) { if (user) {
reset({ reset({
authMethods: user.authMethods, authMethods: user.authMethods
}); });
} }
}, [user]); }, [user]);
const onAuthMethodToggle = async (value: boolean, authMethodOpt: AuthMethodOption) => { const onAuthMethodToggle = async (value: boolean, authMethodOpt: AuthMethodOption) => {
const hasSamlEnabled = user.authMethods const hasSamlEnabled = user.authMethods.some((authMethod: AuthMethod) =>
.some((authMethod: AuthMethod) => samlProviders.includes(authMethod)); samlProviders.includes(authMethod)
);
if (hasSamlEnabled) { if (hasSamlEnabled) {
createNotification({ createNotification({
@@ -73,7 +69,7 @@ export const AuthMethodSection = () => {
const newAuthMethods = value const newAuthMethods = value
? [...authMethods, authMethodOpt.value] ? [...authMethods, authMethodOpt.value]
: authMethods.filter(auth => auth !== authMethodOpt.value); : authMethods.filter((auth) => auth !== authMethodOpt.value);
if (value) { if (value) {
const newUser = await mutateAsync({ const newUser = await mutateAsync({
@@ -105,20 +101,22 @@ export const AuthMethodSection = () => {
text: "Successfully disabled authentication method", text: "Successfully disabled authentication method",
type: "success" type: "success"
}); });
} };
return ( return (
<div className="p-4 bg-mineshaft-900 mb-6 rounded-lg border border-mineshaft-600"> <div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<h2 className="text-xl font-semibold flex-1 text-mineshaft-100 mb-8"> <h2 className="mb-8 flex-1 text-xl font-semibold text-mineshaft-100">
Authentication methods Authentication methods
</h2> </h2>
<p className="text-gray-400 mb-4"> <p className="mb-4 text-gray-400">
By enabling a SSO provider, you are allowing an account with that provider which uses the same email address as your existing Infisical account to be able to log in to Infisical. By enabling a SSO provider, you are allowing an account with that provider which uses the
same email address as your existing Infisical account to be able to log in to Infisical.
</p> </p>
<div className="mb-4"> <div className="mb-4">
{user && authMethodOpts.map((authMethodOpt) => { {user &&
authMethodOpts.map((authMethodOpt) => {
return ( return (
<div className="flex p-4 items-center" key={`auth-method-${authMethodOpt.value}`}> <div className="flex items-center p-4" key={`auth-method-${authMethodOpt.value}`}>
<div className="flex items-center"> <div className="flex items-center">
<FontAwesomeIcon icon={authMethodOpt.icon} className="mr-4" /> <FontAwesomeIcon icon={authMethodOpt.icon} className="mr-4" />
</div> </div>
@@ -127,7 +125,7 @@ export const AuthMethodSection = () => {
onCheckedChange={(value) => onAuthMethodToggle(value, authMethodOpt)} onCheckedChange={(value) => onAuthMethodToggle(value, authMethodOpt)}
isChecked={authMethods?.includes(authMethodOpt.value) ?? false} isChecked={authMethods?.includes(authMethodOpt.value) ?? false}
> >
<p className="w-12 mr-4">{authMethodOpt.label}</p> <p className="mr-4 w-12">{authMethodOpt.label}</p>
</Switch> </Switch>
</div> </div>
); );
@@ -135,4 +133,4 @@ export const AuthMethodSection = () => {
</div> </div>
</div> </div>
); );
} };