diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts
index 655081f84..2e686c260 100644
--- a/backend/src/config/index.ts
+++ b/backend/src/config/index.ts
@@ -36,7 +36,6 @@ export const getClientIdVercel = async () => (await client.getSecret("CLIENT_ID_
export const getClientIdNetlify = async () => (await client.getSecret("CLIENT_ID_NETLIFY")).secretValue;
export const getClientIdGitHub = async () => (await client.getSecret("CLIENT_ID_GITHUB")).secretValue;
export const getClientIdGitLab = async () => (await client.getSecret("CLIENT_ID_GITLAB")).secretValue;
-export const getClientIdGoogle = async () => (await client.getSecret("CLIENT_ID_GOOGLE")).secretValue;
export const getClientIdBitBucket = async () => (await client.getSecret("CLIENT_ID_BITBUCKET")).secretValue;
export const getClientSecretAzure = async () => (await client.getSecret("CLIENT_SECRET_AZURE")).secretValue;
export const getClientSecretHeroku = async () => (await client.getSecret("CLIENT_SECRET_HEROKU")).secretValue;
@@ -44,9 +43,14 @@ export const getClientSecretVercel = async () => (await client.getSecret("CLIENT
export const getClientSecretNetlify = async () => (await client.getSecret("CLIENT_SECRET_NETLIFY")).secretValue;
export const getClientSecretGitHub = async () => (await client.getSecret("CLIENT_SECRET_GITHUB")).secretValue;
export const getClientSecretGitLab = async () => (await client.getSecret("CLIENT_SECRET_GITLAB")).secretValue;
-export const getClientSecretGoogle = async () => (await client.getSecret("CLIENT_SECRET_GOOGLE")).secretValue;
export const getClientSecretBitBucket = async () => (await client.getSecret("CLIENT_SECRET_BITBUCKET")).secretValue;
export const getClientSlugVercel = async () => (await client.getSecret("CLIENT_SLUG_VERCEL")).secretValue;
+
+export const getClientIdGoogleLogin = async () => (await client.getSecret("CLIENT_ID_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 getClientSecretGitHubLogin = async () => (await client.getSecret("CLIENT_SECRET_GITHUB_LOGIN")).secretValue;
+
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 getSentryDSN = async () => (await client.getSecret("SENTRY_DSN")).secretValue;
diff --git a/backend/src/controllers/v2/usersController.ts b/backend/src/controllers/v2/usersController.ts
index 237d32671..66a48b550 100644
--- a/backend/src/controllers/v2/usersController.ts
+++ b/backend/src/controllers/v2/usersController.ts
@@ -123,9 +123,15 @@ export const updateAuthProvider = async (req: Request, res: Response) => {
authProvider
} = req.body;
- if (req.user?.authProvider === AuthProvider.OKTA_SAML) return res.status(400).send({
- message: "Failed to update user authentication method because SAML SSO is enforced"
- });
+ if (
+ req.user?.authProvider === AuthProvider.OKTA_SAML
+ || req.user?.authProvider === AuthProvider.AZURE_SAML
+ || req.user?.authProvider === AuthProvider.JUMPCLOUD_SAML
+ ) {
+ return res.status(400).send({
+ message: "Failed to update user authentication method because SAML SSO is enforced"
+ });
+ }
const user = await User.findByIdAndUpdate(
req.user._id.toString(),
diff --git a/backend/src/ee/routes/v1/sso.ts b/backend/src/ee/routes/v1/sso.ts
index b54aa5942..f76f19e7d 100644
--- a/backend/src/ee/routes/v1/sso.ts
+++ b/backend/src/ee/routes/v1/sso.ts
@@ -41,6 +41,29 @@ router.get(
ssoController.redirectSSO
);
+router.get(
+ "/redirect/github",
+ authLimiter,
+ (req, res, next) => {
+ passport.authenticate("github", {
+ session: false,
+ ...(req.query.callback_port ? {
+ state: req.query.callback_port as string
+ } : {})
+ })(req, res, next);
+ }
+);
+
+router.get(
+ "/github",
+ authLimiter,
+ passport.authenticate("github", {
+ failureRedirect: "/login/provider/error",
+ session: false
+ }),
+ ssoController.redirectSSO
+);
+
router.get(
"/redirect/saml2/:ssoIdentifier",
authLimiter,
diff --git a/backend/src/routes/v1/auth.ts b/backend/src/routes/v1/auth.ts
index f6d90c804..ae85aa36c 100644
--- a/backend/src/routes/v1/auth.ts
+++ b/backend/src/routes/v1/auth.ts
@@ -1,66 +1,10 @@
import express from "express";
const router = express.Router();
import { body } from "express-validator";
-import passport from "passport";
import { requireAuth, validateRequest } from "../../middleware";
import { authController } from "../../controllers/v1";
import { authLimiter } from "../../helpers/rateLimiter";
import { AUTH_MODE_JWT } from "../../variables";
-import { User, AuthProvider } from '../../models';
-import { createToken } from '../../helpers/auth';
-import { getJwtProviderAuthLifetime, getJwtProviderAuthSecret } from '../../config';
-import { ssoController } from "../../ee/controllers/v1";
-
-var GitHubStrategy = require('passport-github').Strategy;
-passport.use(new GitHubStrategy({
- passReqToCallback: true,
- clientID: process.env['CLIENT_ID_GITHUB_LOGIN'],
- clientSecret: process.env['CLIENT_SECRET_GITHUB'],
- callbackURL: "/api/v1/auth/github/callback"
-},
-async (req : express.Request, accessToken : any, refreshToken : any, profile : any, cb : any) => {
- const email = profile.emails[0].value;
- let user = await User.findOne({
- email
- });
- if (!user) {
- user = await new User({
- email: email,
- authProvider: AuthProvider.GITHUB,
- authId: profile.id,
- firstName: profile.displayName,
- }).save();
- }
- const isUserCompleted = true;
- const providerAuthToken = createToken({
- payload: {
- userId: profile.id.toString(),
- email: email,
- isUserCompleted,
- ...(req.query.state ? {
- callbackPort: req.query.state as string
- } : {})
- },
- expiresIn: await getJwtProviderAuthLifetime(),
- secret: await getJwtProviderAuthSecret(),
- });
- req.isUserCompleted = isUserCompleted;
- req.providerAuthToken = providerAuthToken;
- return cb(null, profile);
-}
-));
-
-router.get('/github', passport.authenticate('github', { failureRedirect: '/login/provider/error', session: false }), ssoController.redirectSSO);
-
-router.get('/github/callback',
-passport.authenticate('github', { failureRedirect: '/login/provider/error', session: false }
-),
-function(req, res, next) {
- // Successful authentication, redirect home.
- console.log("github success");
- res.redirect(`/login/sso?token=${encodeURIComponent(req.providerAuthToken)}`);
- next();
-});
router.post("/token", validateRequest, authController.getNewToken);
diff --git a/backend/src/routes/v2/users.ts b/backend/src/routes/v2/users.ts
index 94d912b48..334ef523b 100644
--- a/backend/src/routes/v2/users.ts
+++ b/backend/src/routes/v2/users.ts
@@ -50,7 +50,8 @@ router.patch(
}),
body("authProvider").exists().isString().isIn([
AuthProvider.EMAIL,
- AuthProvider.GOOGLE
+ AuthProvider.GOOGLE,
+ AuthProvider.GITHUB
]),
validateRequest,
usersController.updateAuthProvider
diff --git a/backend/src/utils/auth.ts b/backend/src/utils/auth.ts
index 2dc652460..8faba80bf 100644
--- a/backend/src/utils/auth.ts
+++ b/backend/src/utils/auth.ts
@@ -12,8 +12,10 @@ import {
} from "../models";
import { createToken } from "../helpers/auth";
import {
- getClientIdGoogle,
- getClientSecretGoogle,
+ getClientIdGitHubLogin,
+ getClientIdGoogleLogin,
+ getClientSecretGitHubLogin,
+ getClientSecretGoogleLogin,
getJwtProviderAuthLifetime,
getJwtProviderAuthSecret,
} from "../config";
@@ -25,6 +27,8 @@ import { getSiteURL } from "../config";
// eslint-disable-next-line @typescript-eslint/no-var-requires
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 { MultiSamlStrategy } = require("@node-saml/passport-saml");
/**
@@ -67,42 +71,97 @@ const getAuthDataPayloadUserObj = (authData: AuthData) => {
}
const initializePassport = async () => {
- const googleClientSecret = await getClientSecretGoogle();
- const googleClientId = await getClientIdGoogle();
+ const clientIdGoogleLogin = await getClientIdGoogleLogin();
+ const clientSecretGoogleLogin = await getClientSecretGoogleLogin();
+ const clientIdGitHubLogin = await getClientIdGitHubLogin();
+ const clientSecretGitHubLogin = await getClientSecretGitHubLogin();
- passport.use(new GoogleStrategy({
- passReqToCallback: true,
- clientID: googleClientId,
- clientSecret: googleClientSecret,
- callbackURL: "/api/v1/sso/google",
- scope: ["profile", " email"],
- }, async (
- req: express.Request,
- accessToken: string,
- refreshToken: string,
- profile: any,
- done: any
- ) => {
- try {
+ if (clientIdGoogleLogin && clientSecretGoogleLogin) {
+ passport.use(new GoogleStrategy({
+ passReqToCallback: true,
+ clientID: clientIdGoogleLogin,
+ clientSecret: clientSecretGoogleLogin,
+ callbackURL: "/api/v1/sso/google",
+ scope: ["profile", " email"],
+ }, async (
+ req: express.Request,
+ accessToken: string,
+ refreshToken: string,
+ profile: any,
+ done: any
+ ) => {
+ try {
+ const email = profile.emails[0].value;
+
+ let user = await User.findOne({
+ email
+ }).select("+publicKey");
+
+ if (user && user.authProvider !== AuthProvider.GOOGLE) {
+ done(InternalServerError());
+ }
+
+ if (!user) {
+ user = await new User({
+ email,
+ authProvider: AuthProvider.GOOGLE,
+ authId: profile.id,
+ firstName: profile.name.givenName,
+ lastName: profile.name.familyName
+ }).save();
+ }
+
+ const isUserCompleted = !!user.publicKey;
+ const providerAuthToken = createToken({
+ payload: {
+ userId: user._id.toString(),
+ email: user.email,
+ firstName: user.firstName,
+ lastName: user.lastName,
+ authProvider: user.authProvider,
+ isUserCompleted,
+ ...(req.query.state ? {
+ callbackPort: req.query.state as string
+ } : {})
+ },
+ expiresIn: await getJwtProviderAuthLifetime(),
+ secret: await getJwtProviderAuthSecret(),
+ });
+
+ req.isUserCompleted = isUserCompleted;
+ req.providerAuthToken = providerAuthToken;
+ done(null, profile);
+ } catch (err) {
+ done(null, false);
+ }
+ }));
+ }
+
+ if (clientIdGitHubLogin && clientSecretGitHubLogin) {
+ passport.use(new GitHubStrategy({
+ passReqToCallback: true,
+ clientID: clientIdGitHubLogin,
+ clientSecret: clientSecretGitHubLogin,
+ callbackURL: "/api/v1/sso/github"
+ },
+ async (req : express.Request, accessToken : any, refreshToken : any, profile : any, done : any) => {
const email = profile.emails[0].value;
- const firstName = profile.name.givenName;
- const lastName = profile.name.familyName;
let user = await User.findOne({
email
}).select("+publicKey");
- if (user && user.authProvider !== AuthProvider.GOOGLE) {
+ if (user && user.authProvider !== AuthProvider.GITHUB) {
done(InternalServerError());
}
-
+
if (!user) {
user = await new User({
- email,
- authProvider: AuthProvider.GOOGLE,
+ email: email,
+ authProvider: AuthProvider.GITHUB,
authId: profile.id,
- firstName,
- lastName
+ firstName: profile.displayName,
+ lastName: ""
}).save();
}
@@ -111,8 +170,8 @@ const initializePassport = async () => {
payload: {
userId: user._id.toString(),
email: user.email,
- firstName,
- lastName,
+ firstName: user.firstName,
+ lastName: user.lastName,
authProvider: user.authProvider,
isUserCompleted,
...(req.query.state ? {
@@ -125,11 +184,10 @@ const initializePassport = async () => {
req.isUserCompleted = isUserCompleted;
req.providerAuthToken = providerAuthToken;
- done(null, profile);
- } catch (err) {
- done(null, false);
+ return done(null, profile);
}
- }));
+ ));
+ }
passport.use("saml", new MultiSamlStrategy(
{
diff --git a/backend/src/utils/setup/index.ts b/backend/src/utils/setup/index.ts
index 2f88b2913..aa1e22f90 100644
--- a/backend/src/utils/setup/index.ts
+++ b/backend/src/utils/setup/index.ts
@@ -24,8 +24,6 @@ import {
reencryptSecretBlindIndexDataSalts
} from "./reencryptData";
import {
- getClientIdGoogle,
- getClientSecretGoogle,
getMongoURL,
getNodeEnv,
getSentryDSN
@@ -55,12 +53,7 @@ export const setup = async () => {
// initializing the database connection
await DatabaseService.initDatabase(await getMongoURL());
- const googleClientSecret: string = await getClientSecretGoogle();
- const googleClientId: string = await getClientIdGoogle();
-
- if (googleClientId && googleClientSecret) {
- await initializePassport();
- }
+ await initializePassport();
// re-encrypt any data previously encrypted under server hex 128-bit ENCRYPTION_KEY
// to base64 256-bit ROOT_ENCRYPTION_KEY
diff --git a/docs/self-hosting/configuration/envars.mdx b/docs/self-hosting/configuration/envars.mdx
index 1db882260..d355140b6 100644
--- a/docs/self-hosting/configuration/envars.mdx
+++ b/docs/self-hosting/configuration/envars.mdx
@@ -5,7 +5,7 @@ description: "Configure your environment variables when self-hosting Infisical."
## Backend environment variables
-Depending on your choosen self hosted deployment method, you may need to configured at least the required environment variable listed below.
+Depending on your choosen self hosted deployment method, you may need to configured at least the required environment variable listed below.
Other environment variables are listed below to increase the functionality of your self hosted instance based on your use case.