From 0d74752169cdc1fe527fa522dca9d47b44c589f8 Mon Sep 17 00:00:00 2001 From: Andrew Atimapre Date: Sun, 24 Sep 2023 22:33:00 +0100 Subject: [PATCH] Integrated login with Gitlab --- backend/src/utils/auth.ts | 59 +++++++ .../components/signup/InitialSignupStep.tsx | 154 ++++++++++-------- 2 files changed, 146 insertions(+), 67 deletions(-) diff --git a/backend/src/utils/auth.ts b/backend/src/utils/auth.ts index f7a1a504c..44cb68652 100644 --- a/backend/src/utils/auth.ts +++ b/backend/src/utils/auth.ts @@ -13,8 +13,10 @@ import { import { createToken } from "../helpers/auth"; import { getClientIdGitHubLogin, + getClientIdGitLabLogin, getClientIdGoogleLogin, getClientSecretGitHubLogin, + getClientSecretGitLabLogin, getClientSecretGoogleLogin, getJwtProviderAuthLifetime, getJwtProviderAuthSecret, @@ -29,6 +31,8 @@ const GoogleStrategy = require("passport-google-oauth20").Strategy; // eslint-disable-next-line @typescript-eslint/no-var-requires const GitHubStrategy = require("passport-github").Strategy; // eslint-disable-next-line @typescript-eslint/no-var-requires +const GitLabStrategy = require("passport-gitlab2").Strategy; +// eslint-disable-next-line @typescript-eslint/no-var-requires const { MultiSamlStrategy } = require("@node-saml/passport-saml"); /** @@ -75,6 +79,8 @@ const initializePassport = async () => { const clientSecretGoogleLogin = await getClientSecretGoogleLogin(); const clientIdGitHubLogin = await getClientIdGitHubLogin(); const clientSecretGitHubLogin = await getClientSecretGitHubLogin(); + const clientIdGitLabLogin = await getClientIdGitLabLogin(); + const clientSecretGitLabLogin = await getClientSecretGitLabLogin(); if (clientIdGoogleLogin && clientSecretGoogleLogin) { passport.use(new GoogleStrategy({ @@ -190,6 +196,59 @@ const initializePassport = async () => { } )); } + + if (clientIdGitLabLogin && clientSecretGitLabLogin) { + passport.use(new GitLabStrategy({ + passReqToCallback: true, + clientID: clientIdGitLabLogin, + clientSecret: clientSecretGitLabLogin, + callbackURL: "/api/v1/sso/gitlab" + }, + async (req : express.Request, accessToken : any, refreshToken : any, profile : any, done : any) => { + const email = profile.emails[0].value; + + let user = await User.findOne({ + email + }).select("+publicKey"); + + if (!user) { + user = await new User({ + email: email, + authMethods: [AuthMethod.GITLAB], + firstName: profile.displayName, + lastName: "" + }).save(); + } + + let isLinkingRequired = false; + if (!user.authMethods.includes(AuthMethod.GITLAB)) { + isLinkingRequired = true; + } + + const isUserCompleted = !!user.publicKey; + const providerAuthToken = createToken({ + payload: { + userId: user._id.toString(), + email: user.email, + firstName: user.firstName, + lastName: user.lastName, + authMethod: AuthMethod.GITLAB, + isUserCompleted, + isLinkingRequired, + ...(req.query.state ? { + callbackPort: req.query.state as string + } : {}) + }, + expiresIn: await getJwtProviderAuthLifetime(), + secret: await getJwtProviderAuthSecret(), + }); + + req.isUserCompleted = isUserCompleted; + req.providerAuthToken = providerAuthToken; + return done(null, profile); + } + )); + } passport.use("saml", new MultiSamlStrategy( { diff --git a/frontend/src/components/signup/InitialSignupStep.tsx b/frontend/src/components/signup/InitialSignupStep.tsx index 0a1248b2d..7953ff0df 100644 --- a/frontend/src/components/signup/InitialSignupStep.tsx +++ b/frontend/src/components/signup/InitialSignupStep.tsx @@ -1,7 +1,7 @@ import { useTranslation } from "react-i18next"; import Link from "next/link"; 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 { faEnvelope } from "@fortawesome/free-regular-svg-icons"; import { faLock } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -9,74 +9,94 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Button } from "../v2"; export default function InitialSignupStep({ - setIsSignupWithEmail, + setIsSignupWithEmail }: { - setIsSignupWithEmail: (value: boolean) => void + setIsSignupWithEmail: (value: boolean) => void; }) { - const { t } = useTranslation(); - const router = useRouter(); + const { t } = useTranslation(); + const router = useRouter(); - return
-

{t("signup.initial-title")}

-
- -
-
- -
-
- -
-
- -
-
- {t("signup.create-policy")} -
-
- - {t("signup.already-have-account")} - -
+ return ( +
+

+ {t("signup.initial-title")} +

+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ {t("signup.create-policy")} +
+
+ + + {t("signup.already-have-account")} + + +
+ ); }