mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 04:27:29 +00:00
Revise and finish login with GitHub
This commit is contained in:
@@ -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 getClientIdNetlify = async () => (await client.getSecret("CLIENT_ID_NETLIFY")).secretValue;
|
||||||
export const getClientIdGitHub = async () => (await client.getSecret("CLIENT_ID_GITHUB")).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 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 getClientIdBitBucket = async () => (await client.getSecret("CLIENT_ID_BITBUCKET")).secretValue;
|
||||||
export const getClientSecretAzure = async () => (await client.getSecret("CLIENT_SECRET_AZURE")).secretValue;
|
export const getClientSecretAzure = async () => (await client.getSecret("CLIENT_SECRET_AZURE")).secretValue;
|
||||||
export const getClientSecretHeroku = async () => (await client.getSecret("CLIENT_SECRET_HEROKU")).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 getClientSecretNetlify = async () => (await client.getSecret("CLIENT_SECRET_NETLIFY")).secretValue;
|
||||||
export const getClientSecretGitHub = async () => (await client.getSecret("CLIENT_SECRET_GITHUB")).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 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 getClientSecretBitBucket = async () => (await client.getSecret("CLIENT_SECRET_BITBUCKET")).secretValue;
|
||||||
export const getClientSlugVercel = async () => (await client.getSecret("CLIENT_SLUG_VERCEL")).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 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";
|
||||||
export const getSentryDSN = async () => (await client.getSecret("SENTRY_DSN")).secretValue;
|
export const getSentryDSN = async () => (await client.getSecret("SENTRY_DSN")).secretValue;
|
||||||
|
|||||||
@@ -123,9 +123,15 @@ export const updateAuthProvider = async (req: Request, res: Response) => {
|
|||||||
authProvider
|
authProvider
|
||||||
} = req.body;
|
} = req.body;
|
||||||
|
|
||||||
if (req.user?.authProvider === AuthProvider.OKTA_SAML) return res.status(400).send({
|
if (
|
||||||
message: "Failed to update user authentication method because SAML SSO is enforced"
|
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(
|
const user = await User.findByIdAndUpdate(
|
||||||
req.user._id.toString(),
|
req.user._id.toString(),
|
||||||
|
|||||||
@@ -41,6 +41,29 @@ router.get(
|
|||||||
ssoController.redirectSSO
|
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(
|
router.get(
|
||||||
"/redirect/saml2/:ssoIdentifier",
|
"/redirect/saml2/:ssoIdentifier",
|
||||||
authLimiter,
|
authLimiter,
|
||||||
|
|||||||
@@ -1,66 +1,10 @@
|
|||||||
import express from "express";
|
import express from "express";
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
import { body } from "express-validator";
|
import { body } from "express-validator";
|
||||||
import passport from "passport";
|
|
||||||
import { requireAuth, validateRequest } from "../../middleware";
|
import { requireAuth, validateRequest } from "../../middleware";
|
||||||
import { authController } from "../../controllers/v1";
|
import { authController } from "../../controllers/v1";
|
||||||
import { authLimiter } from "../../helpers/rateLimiter";
|
import { authLimiter } from "../../helpers/rateLimiter";
|
||||||
import { AUTH_MODE_JWT } from "../../variables";
|
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);
|
router.post("/token", validateRequest, authController.getNewToken);
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ router.patch(
|
|||||||
}),
|
}),
|
||||||
body("authProvider").exists().isString().isIn([
|
body("authProvider").exists().isString().isIn([
|
||||||
AuthProvider.EMAIL,
|
AuthProvider.EMAIL,
|
||||||
AuthProvider.GOOGLE
|
AuthProvider.GOOGLE,
|
||||||
|
AuthProvider.GITHUB
|
||||||
]),
|
]),
|
||||||
validateRequest,
|
validateRequest,
|
||||||
usersController.updateAuthProvider
|
usersController.updateAuthProvider
|
||||||
|
|||||||
+90
-32
@@ -12,8 +12,10 @@ import {
|
|||||||
} from "../models";
|
} from "../models";
|
||||||
import { createToken } from "../helpers/auth";
|
import { createToken } from "../helpers/auth";
|
||||||
import {
|
import {
|
||||||
getClientIdGoogle,
|
getClientIdGitHubLogin,
|
||||||
getClientSecretGoogle,
|
getClientIdGoogleLogin,
|
||||||
|
getClientSecretGitHubLogin,
|
||||||
|
getClientSecretGoogleLogin,
|
||||||
getJwtProviderAuthLifetime,
|
getJwtProviderAuthLifetime,
|
||||||
getJwtProviderAuthSecret,
|
getJwtProviderAuthSecret,
|
||||||
} from "../config";
|
} from "../config";
|
||||||
@@ -25,6 +27,8 @@ import { getSiteURL } from "../config";
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const GoogleStrategy = require("passport-google-oauth20").Strategy;
|
const GoogleStrategy = require("passport-google-oauth20").Strategy;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// 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");
|
const { MultiSamlStrategy } = require("@node-saml/passport-saml");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,42 +71,97 @@ const getAuthDataPayloadUserObj = (authData: AuthData) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const initializePassport = async () => {
|
const initializePassport = async () => {
|
||||||
const googleClientSecret = await getClientSecretGoogle();
|
const clientIdGoogleLogin = await getClientIdGoogleLogin();
|
||||||
const googleClientId = await getClientIdGoogle();
|
const clientSecretGoogleLogin = await getClientSecretGoogleLogin();
|
||||||
|
const clientIdGitHubLogin = await getClientIdGitHubLogin();
|
||||||
|
const clientSecretGitHubLogin = await getClientSecretGitHubLogin();
|
||||||
|
|
||||||
passport.use(new GoogleStrategy({
|
if (clientIdGoogleLogin && clientSecretGoogleLogin) {
|
||||||
passReqToCallback: true,
|
passport.use(new GoogleStrategy({
|
||||||
clientID: googleClientId,
|
passReqToCallback: true,
|
||||||
clientSecret: googleClientSecret,
|
clientID: clientIdGoogleLogin,
|
||||||
callbackURL: "/api/v1/sso/google",
|
clientSecret: clientSecretGoogleLogin,
|
||||||
scope: ["profile", " email"],
|
callbackURL: "/api/v1/sso/google",
|
||||||
}, async (
|
scope: ["profile", " email"],
|
||||||
req: express.Request,
|
}, async (
|
||||||
accessToken: string,
|
req: express.Request,
|
||||||
refreshToken: string,
|
accessToken: string,
|
||||||
profile: any,
|
refreshToken: string,
|
||||||
done: any
|
profile: any,
|
||||||
) => {
|
done: any
|
||||||
try {
|
) => {
|
||||||
|
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 email = profile.emails[0].value;
|
||||||
const firstName = profile.name.givenName;
|
|
||||||
const lastName = profile.name.familyName;
|
|
||||||
|
|
||||||
let user = await User.findOne({
|
let user = await User.findOne({
|
||||||
email
|
email
|
||||||
}).select("+publicKey");
|
}).select("+publicKey");
|
||||||
|
|
||||||
if (user && user.authProvider !== AuthProvider.GOOGLE) {
|
if (user && user.authProvider !== AuthProvider.GITHUB) {
|
||||||
done(InternalServerError());
|
done(InternalServerError());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
user = await new User({
|
user = await new User({
|
||||||
email,
|
email: email,
|
||||||
authProvider: AuthProvider.GOOGLE,
|
authProvider: AuthProvider.GITHUB,
|
||||||
authId: profile.id,
|
authId: profile.id,
|
||||||
firstName,
|
firstName: profile.displayName,
|
||||||
lastName
|
lastName: ""
|
||||||
}).save();
|
}).save();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,8 +170,8 @@ const initializePassport = async () => {
|
|||||||
payload: {
|
payload: {
|
||||||
userId: user._id.toString(),
|
userId: user._id.toString(),
|
||||||
email: user.email,
|
email: user.email,
|
||||||
firstName,
|
firstName: user.firstName,
|
||||||
lastName,
|
lastName: user.lastName,
|
||||||
authProvider: user.authProvider,
|
authProvider: user.authProvider,
|
||||||
isUserCompleted,
|
isUserCompleted,
|
||||||
...(req.query.state ? {
|
...(req.query.state ? {
|
||||||
@@ -125,11 +184,10 @@ const initializePassport = async () => {
|
|||||||
|
|
||||||
req.isUserCompleted = isUserCompleted;
|
req.isUserCompleted = isUserCompleted;
|
||||||
req.providerAuthToken = providerAuthToken;
|
req.providerAuthToken = providerAuthToken;
|
||||||
done(null, profile);
|
return done(null, profile);
|
||||||
} catch (err) {
|
|
||||||
done(null, false);
|
|
||||||
}
|
}
|
||||||
}));
|
));
|
||||||
|
}
|
||||||
|
|
||||||
passport.use("saml", new MultiSamlStrategy(
|
passport.use("saml", new MultiSamlStrategy(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ import {
|
|||||||
reencryptSecretBlindIndexDataSalts
|
reencryptSecretBlindIndexDataSalts
|
||||||
} from "./reencryptData";
|
} from "./reencryptData";
|
||||||
import {
|
import {
|
||||||
getClientIdGoogle,
|
|
||||||
getClientSecretGoogle,
|
|
||||||
getMongoURL,
|
getMongoURL,
|
||||||
getNodeEnv,
|
getNodeEnv,
|
||||||
getSentryDSN
|
getSentryDSN
|
||||||
@@ -55,12 +53,7 @@ export const setup = async () => {
|
|||||||
// initializing the database connection
|
// initializing the database connection
|
||||||
await DatabaseService.initDatabase(await getMongoURL());
|
await DatabaseService.initDatabase(await getMongoURL());
|
||||||
|
|
||||||
const googleClientSecret: string = await getClientSecretGoogle();
|
await initializePassport();
|
||||||
const googleClientId: string = await getClientIdGoogle();
|
|
||||||
|
|
||||||
if (googleClientId && googleClientSecret) {
|
|
||||||
await initializePassport();
|
|
||||||
}
|
|
||||||
|
|
||||||
// re-encrypt any data previously encrypted under server hex 128-bit ENCRYPTION_KEY
|
// re-encrypt any data previously encrypted under server hex 128-bit ENCRYPTION_KEY
|
||||||
// to base64 256-bit ROOT_ENCRYPTION_KEY
|
// to base64 256-bit ROOT_ENCRYPTION_KEY
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ description: "Configure your environment variables when self-hosting Infisical."
|
|||||||
|
|
||||||
## Backend environment variables
|
## 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.
|
Other environment variables are listed below to increase the functionality of your self hosted instance based on your use case.
|
||||||
|
|
||||||
<Tabs>
|
<Tabs>
|
||||||
@@ -14,25 +14,40 @@ Other environment variables are listed below to increase the functionality of yo
|
|||||||
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16`
|
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16`
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="JWT_SIGNUP_SECRET" type="string" default="none" required>
|
{" "}
|
||||||
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16`
|
|
||||||
</ParamField>
|
|
||||||
|
|
||||||
<ParamField query="JWT_REFRESH_SECRET" type="string" default="none" required>
|
<ParamField query="JWT_SIGNUP_SECRET" type="string" default="none" required>
|
||||||
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16`
|
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex
|
||||||
</ParamField>
|
16`
|
||||||
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="JWT_AUTH_SECRET" type="string" default="none" required>
|
{" "}
|
||||||
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16`
|
|
||||||
</ParamField>
|
|
||||||
|
|
||||||
<ParamField query="JWT_MFA_SECRET" type="string" default="none" required>
|
<ParamField query="JWT_REFRESH_SECRET" type="string" default="none" required>
|
||||||
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16`
|
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex
|
||||||
</ParamField>
|
16`
|
||||||
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="JWT_SERVICE_SECRET" type="string" default="none" required>
|
{" "}
|
||||||
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16`
|
|
||||||
</ParamField>
|
<ParamField query="JWT_AUTH_SECRET" type="string" default="none" required>
|
||||||
|
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex
|
||||||
|
16`
|
||||||
|
</ParamField>
|
||||||
|
|
||||||
|
{" "}
|
||||||
|
|
||||||
|
<ParamField query="JWT_MFA_SECRET" type="string" default="none" required>
|
||||||
|
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex
|
||||||
|
16`
|
||||||
|
</ParamField>
|
||||||
|
|
||||||
|
{" "}
|
||||||
|
|
||||||
|
<ParamField query="JWT_SERVICE_SECRET" type="string" default="none" required>
|
||||||
|
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex
|
||||||
|
16`
|
||||||
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="MONGO_URL" type="string" default="none" required>
|
<ParamField query="MONGO_URL" type="string" default="none" required>
|
||||||
*TLS based connection string is not yet supported
|
*TLS based connection string is not yet supported
|
||||||
@@ -58,7 +73,7 @@ Other environment variables are listed below to increase the functionality of yo
|
|||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="SMTP_SECURE" type="string" default="none" optional>
|
<ParamField query="SMTP_SECURE" type="string" default="none" optional>
|
||||||
If true, use TLS when connecting to host. If false, TLS will be used if STARTTLS is supported
|
If true, use TLS when connecting to host. If false, TLS will be used if STARTTLS is supported
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="SMTP_FROM_ADDRESS" type="string" default="none" optional>
|
<ParamField query="SMTP_FROM_ADDRESS" type="string" default="none" optional>
|
||||||
@@ -68,9 +83,10 @@ Other environment variables are listed below to increase the functionality of yo
|
|||||||
<ParamField query="SMTP_FROM_NAME" type="string" default="none" optional>
|
<ParamField query="SMTP_FROM_NAME" type="string" default="none" optional>
|
||||||
Name label to be used in From field (e.g. Team)
|
Name label to be used in From field (e.g. Team)
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="Secret Integrations">
|
<Tab title="Secret Integrations">
|
||||||
To sync secret to third party services, provide value for the related services
|
To sync secret to third party services, provide value for the related services
|
||||||
|
|
||||||
<ParamField query="CLIENT_ID_HEROKU" type="string" default="none" optional>
|
<ParamField query="CLIENT_ID_HEROKU" type="string" default="none" optional>
|
||||||
OAuth2 client ID for Heroku integration
|
OAuth2 client ID for Heroku integration
|
||||||
@@ -81,7 +97,7 @@ Other environment variables are listed below to increase the functionality of yo
|
|||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="CLIENT_ID_VERCEL" type="string" default="none" optional>
|
<ParamField query="CLIENT_ID_VERCEL" type="string" default="none" optional>
|
||||||
OAuth2 client ID for Vercel integration
|
OAuth2 client ID for Vercel integration
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="CLIENT_SECRET_VERCEL" type="string" default="none" optional>
|
<ParamField query="CLIENT_SECRET_VERCEL" type="string" default="none" optional>
|
||||||
@@ -89,7 +105,7 @@ Other environment variables are listed below to increase the functionality of yo
|
|||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="CLIENT_ID_NETLIFY" type="string" default="none" optional>
|
<ParamField query="CLIENT_ID_NETLIFY" type="string" default="none" optional>
|
||||||
OAuth2 client ID for Netlify integration
|
OAuth2 client ID for Netlify integration
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="CLIENT_SECRET_NETLIFY" type="string" default="none" optional>
|
<ParamField query="CLIENT_SECRET_NETLIFY" type="string" default="none" optional>
|
||||||
@@ -97,7 +113,7 @@ Other environment variables are listed below to increase the functionality of yo
|
|||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="CLIENT_ID_GITHUB" type="string" default="none" optional>
|
<ParamField query="CLIENT_ID_GITHUB" type="string" default="none" optional>
|
||||||
OAuth2 client ID for GitHub integration
|
OAuth2 client ID for GitHub integration
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="CLIENT_SECRET_GITHUB" type="string" default="none" optional>
|
<ParamField query="CLIENT_SECRET_GITHUB" type="string" default="none" optional>
|
||||||
@@ -109,23 +125,30 @@ Other environment variables are listed below to increase the functionality of yo
|
|||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="CLIENT_ID_BITBUCKET" type="string" default="none" optional>
|
<ParamField query="CLIENT_ID_BITBUCKET" type="string" default="none" optional>
|
||||||
OAuth2 client ID for BitBucket integration
|
OAuth2 client ID for BitBucket integration
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="CLIENT_SECRET_BITBUCKET" type="string" default="none" optional>
|
<ParamField query="CLIENT_SECRET_BITBUCKET" type="string" default="none" optional>
|
||||||
OAuth2 client secret for BitBucket integration
|
OAuth2 client secret for BitBucket integration
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="Auth Integrations">
|
<Tab title="Auth Integrations">
|
||||||
To integrate with external auth providers, provide value for the related keys
|
To integrate with external auth providers, provide value for the related keys
|
||||||
<ParamField query="JWT_PROVIDER_AUTH_SECRET" type="string" required>
|
<ParamField query="JWT_PROVIDER_AUTH_SECRET" type="string" required>
|
||||||
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16`
|
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16`
|
||||||
</ParamField>
|
</ParamField>
|
||||||
<ParamField query="CLIENT_ID_GOOGLE" type="string" default="none" optional>
|
<ParamField query="CLIENT_ID_GOOGLE_LOGIN" type="string" default="none" optional>
|
||||||
OAuth2 client ID for Google auth integration
|
OAuth2 client ID for Google login
|
||||||
</ParamField>
|
</ParamField>
|
||||||
<ParamField query="CLIENT_SECRET_GOOGLE" type="string" default="none" optional>
|
<ParamField query="CLIENT_SECRET_GOOGLE_LOGIN" type="string" default="none" optional>
|
||||||
OAuth2 client secret for Google auth integration
|
OAuth2 client secret for Google login
|
||||||
|
</ParamField>
|
||||||
|
<ParamField query="CLIENT_ID_GITHUB_LOGIN" type="string" default="none" optional>
|
||||||
|
OAuth2 client ID for GitHub login
|
||||||
|
</ParamField>
|
||||||
|
<ParamField query="CLIENT_SECRET_GITHUB_LOGIN" type="string" default="none" optional>
|
||||||
|
OAuth2 client secret for GitHub login
|
||||||
</ParamField>
|
</ParamField>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="Others">
|
<Tab title="Others">
|
||||||
@@ -150,18 +173,44 @@ Other environment variables are listed below to increase the functionality of yo
|
|||||||
JWT token lifetime expressed in seconds or a string describing a time span
|
JWT token lifetime expressed in seconds or a string describing a time span
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="MONGO_USERNAME" type="string" default="none" optional></ParamField>
|
{" "}
|
||||||
|
|
||||||
<ParamField query="MONGO_PASSWORD" type="string" default="none" optional></ParamField>
|
<ParamField
|
||||||
|
query="MONGO_USERNAME"
|
||||||
|
type="string"
|
||||||
|
default="none"
|
||||||
|
optional
|
||||||
|
></ParamField>
|
||||||
|
|
||||||
#### Error logging
|
{" "}
|
||||||
Infisical uses Sentry to report error logs
|
|
||||||
<ParamField query="SENTRY_DSN" type="string" default="none" optional></ParamField>
|
|
||||||
|
|
||||||
#### Settings
|
<ParamField
|
||||||
<ParamField query="INVITE_ONLY_SIGNUP" type="string" default="false" optional>
|
query="MONGO_PASSWORD"
|
||||||
Only allow users who are invited to sign up
|
type="string"
|
||||||
</ParamField>
|
default="none"
|
||||||
|
optional
|
||||||
|
></ParamField>
|
||||||
|
|
||||||
|
#### Error logging
|
||||||
|
|
||||||
|
Infisical uses Sentry to report error logs
|
||||||
|
|
||||||
|
{" "}
|
||||||
|
|
||||||
|
<ParamField
|
||||||
|
query="SENTRY_DSN"
|
||||||
|
type="string"
|
||||||
|
default="none"
|
||||||
|
optional
|
||||||
|
></ParamField>
|
||||||
|
|
||||||
|
#### Settings
|
||||||
|
|
||||||
|
{" "}
|
||||||
|
|
||||||
|
<ParamField query="INVITE_ONLY_SIGNUP" type="string" default="false" optional>
|
||||||
|
Only allow users who are invited to sign up
|
||||||
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="SITE_URL" type="string" default="none" optional>
|
<ParamField query="SITE_URL" type="string" default="none" optional>
|
||||||
Site URL - should be an absolute URL including the protocol (e.g. https://app.infisical.com)
|
Site URL - should be an absolute URL including the protocol (e.g. https://app.infisical.com)
|
||||||
@@ -170,6 +219,11 @@ Other environment variables are listed below to increase the functionality of yo
|
|||||||
</Tab>
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
|
||||||
## Frontend environment variables
|
## Frontend environment variables
|
||||||
<ParamField query="TELEMETRY_ENABLED" type="string" default="true" optional></ParamField>
|
|
||||||
|
<ParamField
|
||||||
|
query="TELEMETRY_ENABLED"
|
||||||
|
type="string"
|
||||||
|
default="true"
|
||||||
|
optional
|
||||||
|
></ParamField>
|
||||||
|
|||||||
@@ -293,12 +293,10 @@ export const useRevokeMySessions = () => {
|
|||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async () => {
|
mutationFn: async () => {
|
||||||
console.log("useRevokeAllSessions 1");
|
|
||||||
const { data } = await apiRequest.delete(
|
const { data } = await apiRequest.delete(
|
||||||
"/api/v2/users/me/sessions"
|
"/api/v2/users/me/sessions"
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("useRevokeAllSessions 2: ", data);
|
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ 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 { faGoogle } from "@fortawesome/free-brands-svg-icons";
|
import { faGithub,faGoogle } from "@fortawesome/free-brands-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import axios from "axios"
|
import axios from "axios"
|
||||||
|
|
||||||
@@ -34,7 +34,6 @@ export const InitialStep = ({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [loginError, setLoginError] = useState(false);
|
const [loginError, setLoginError] = useState(false);
|
||||||
const [loginEmailChosen, setLoginEmailChosen] = useState(false);
|
|
||||||
const { data: serverDetails } = useFetchServerStatus();
|
const { data: serverDetails } = useFetchServerStatus();
|
||||||
const queryParams = new URLSearchParams(window.location.search);
|
const queryParams = new URLSearchParams(window.location.search);
|
||||||
|
|
||||||
@@ -68,8 +67,7 @@ export const InitialStep = ({
|
|||||||
|
|
||||||
// send request to server endpoint
|
// send request to server endpoint
|
||||||
const instance = axios.create()
|
const instance = axios.create()
|
||||||
const cliResp = await instance.post(cliUrl, { ...isCliLoginSuccessful.loginResponse })
|
await instance.post(cliUrl, { ...isCliLoginSuccessful.loginResponse })
|
||||||
console.log(cliResp)
|
|
||||||
|
|
||||||
// cli page
|
// cli page
|
||||||
router.push("/cli-redirect");
|
router.push("/cli-redirect");
|
||||||
@@ -118,23 +116,6 @@ export const InitialStep = ({
|
|||||||
return (
|
return (
|
||||||
<form onSubmit={handleLogin} className='flex flex-col mx-auto w-full justify-center items-center'>
|
<form onSubmit={handleLogin} className='flex flex-col mx-auto w-full justify-center items-center'>
|
||||||
<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>
|
<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>
|
||||||
<div className='lg:w-1/6 w-1/4 min-w-[21.2rem] md:min-w-[20.1rem] text-center rounded-md mt-4'>
|
|
||||||
<Button
|
|
||||||
colorSchema="primary"
|
|
||||||
variant={loginEmailChosen ? "outline_bg" : "solid"}
|
|
||||||
onClick={() => {
|
|
||||||
const callbackPort = queryParams.get("callback_port");
|
|
||||||
|
|
||||||
window.open(`/api/v1/sso/redirect/google${callbackPort ? `?callback_port=${callbackPort}` : ""}`);
|
|
||||||
window.close();
|
|
||||||
}}
|
|
||||||
leftIcon={<FontAwesomeIcon icon={faGoogle} className="mr-1" />}
|
|
||||||
className="h-12 w-full mx-0"
|
|
||||||
>
|
|
||||||
{t("login.continue-with-google")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
{loginEmailChosen && <>
|
|
||||||
<div className='lg:w-1/6 w-1/4 min-w-[20rem] flex flex-row items-center my-4 py-2'>
|
<div className='lg:w-1/6 w-1/4 min-w-[20rem] flex flex-row items-center my-4 py-2'>
|
||||||
<div className='w-full border-t border-mineshaft-500' />
|
<div className='w-full border-t border-mineshaft-500' />
|
||||||
</div>
|
</div>
|
||||||
@@ -175,19 +156,40 @@ export const InitialStep = ({
|
|||||||
{!isLoading && loginError && <Error text={t("login.error-login") ?? ""} />}
|
{!isLoading && loginError && <Error text={t("login.error-login") ?? ""} />}
|
||||||
<div className='lg:w-1/6 w-1/4 min-w-[20rem] flex flex-row items-center mt-4 py-2'>
|
<div className='lg:w-1/6 w-1/4 min-w-[20rem] flex flex-row items-center mt-4 py-2'>
|
||||||
<div className='w-full border-t border-mineshaft-500' />
|
<div className='w-full border-t border-mineshaft-500' />
|
||||||
</div></>}
|
</div>
|
||||||
{!loginEmailChosen && <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='lg:w-1/6 w-1/4 min-w-[21.2rem] md:min-w-[20.1rem] text-center rounded-md mt-4'>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
colorSchema="primary"
|
||||||
setLoginEmailChosen(true);
|
|
||||||
}}
|
|
||||||
size="sm"
|
|
||||||
isFullWidth
|
|
||||||
className='h-12'
|
|
||||||
colorSchema="primary"
|
|
||||||
variant="outline_bg"
|
variant="outline_bg"
|
||||||
> Continue with Email </Button>
|
onClick={() => {
|
||||||
</div>}
|
const callbackPort = queryParams.get("callback_port");
|
||||||
|
|
||||||
|
window.open(`/api/v1/sso/redirect/google${callbackPort ? `?callback_port=${callbackPort}` : ""}`);
|
||||||
|
window.close();
|
||||||
|
}}
|
||||||
|
leftIcon={<FontAwesomeIcon icon={faGoogle} className="mr-2" />}
|
||||||
|
className="h-12 w-full mx-0"
|
||||||
|
>
|
||||||
|
{t("login.continue-with-google")}
|
||||||
|
</Button>
|
||||||
|
</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'>
|
||||||
|
<Button
|
||||||
|
colorSchema="primary"
|
||||||
|
variant="outline_bg"
|
||||||
|
onClick={() => {
|
||||||
|
const callbackPort = queryParams.get("callback_port");
|
||||||
|
|
||||||
|
window.open(`/api/v1/sso/redirect/github${callbackPort ? `?callback_port=${callbackPort}` : ""}`);
|
||||||
|
|
||||||
|
window.close();
|
||||||
|
}}
|
||||||
|
leftIcon={<FontAwesomeIcon icon={faGithub} className="mr-2" />}
|
||||||
|
className="h-12 w-full mx-0"
|
||||||
|
>
|
||||||
|
Continue with GitHub
|
||||||
|
</Button>
|
||||||
|
</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='lg:w-1/6 w-1/4 min-w-[21.2rem] md:min-w-[20.1rem] text-center rounded-md mt-4'>
|
||||||
<Button
|
<Button
|
||||||
colorSchema="primary"
|
colorSchema="primary"
|
||||||
|
|||||||
+10
-3
@@ -17,7 +17,10 @@ import {
|
|||||||
const authMethods = [
|
const authMethods = [
|
||||||
{ label: "Email", value: "email" },
|
{ label: "Email", value: "email" },
|
||||||
{ label: "Google SSO", value: "google" },
|
{ label: "Google SSO", value: "google" },
|
||||||
{ label: "Okta SAML 2.0", value: "okta-saml" },
|
{ label: "GitHub SSO", value: "github" },
|
||||||
|
{ label: "Okta SAML", value: "okta-saml" },
|
||||||
|
{ label: "Azure SAML", value: "azure-saml" },
|
||||||
|
{ label: "JumpCloud SAML", value: "jumpcloud-saml" }
|
||||||
];
|
];
|
||||||
|
|
||||||
const schema = yup.object({
|
const schema = yup.object({
|
||||||
@@ -54,9 +57,13 @@ export const AuthMethodSection = () => {
|
|||||||
authMethod
|
authMethod
|
||||||
}: FormData) => {
|
}: FormData) => {
|
||||||
try {
|
try {
|
||||||
if (authMethod === "okta-saml") {
|
if (
|
||||||
|
authMethod === "okta-saml"
|
||||||
|
|| authMethod === "azure-saml"
|
||||||
|
|| authMethod === "jumpcloud-saml"
|
||||||
|
) {
|
||||||
createNotification({
|
createNotification({
|
||||||
text: "Okta SAML 2.0 can only be configured in your organization settings",
|
text: "SAML authentication can only be configured in your organization settings",
|
||||||
type: "error"
|
type: "error"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user