mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat: integrated oidc with sso login
This commit is contained in:
@@ -59,7 +59,7 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
||||
const oidcStrategy = await server.services.oidc.getOrgAuthStrategy(oidcOrgSlug);
|
||||
await (
|
||||
passport.authenticate(oidcStrategy as Strategy, {
|
||||
failureRedirect: "/api/v1/oidc/login/error",
|
||||
failureRedirect: "/api/v1/sso/oidc/login/error",
|
||||
session: false,
|
||||
failureMessage: true
|
||||
}) as any
|
||||
@@ -137,13 +137,13 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
||||
schema: {
|
||||
body: z
|
||||
.object({
|
||||
issuer: z.string(),
|
||||
authorizationEndpoint: z.string(),
|
||||
jwksUri: z.string(),
|
||||
tokenEndpoint: z.string(),
|
||||
userinfoEndpoint: z.string(),
|
||||
clientId: z.string(),
|
||||
clientSecret: z.string(),
|
||||
issuer: z.string().trim(),
|
||||
authorizationEndpoint: z.string().trim(),
|
||||
jwksUri: z.string().trim(),
|
||||
tokenEndpoint: z.string().trim(),
|
||||
userinfoEndpoint: z.string().trim(),
|
||||
clientId: z.string().trim(),
|
||||
clientSecret: z.string().trim(),
|
||||
isActive: z.boolean()
|
||||
})
|
||||
.partial()
|
||||
@@ -182,15 +182,15 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
body: z.object({
|
||||
issuer: z.string(),
|
||||
authorizationEndpoint: z.string(),
|
||||
jwksUri: z.string(),
|
||||
tokenEndpoint: z.string(),
|
||||
userinfoEndpoint: z.string(),
|
||||
clientId: z.string(),
|
||||
clientSecret: z.string(),
|
||||
issuer: z.string().trim(),
|
||||
authorizationEndpoint: z.string().trim(),
|
||||
jwksUri: z.string().trim(),
|
||||
tokenEndpoint: z.string().trim(),
|
||||
userinfoEndpoint: z.string().trim(),
|
||||
clientId: z.string().trim(),
|
||||
clientSecret: z.string().trim(),
|
||||
isActive: z.boolean(),
|
||||
orgSlug: z.string()
|
||||
orgSlug: z.string().trim()
|
||||
}),
|
||||
response: {
|
||||
200: OidcConfigsSchema.pick({
|
||||
|
||||
@@ -520,7 +520,7 @@ export const oidcConfigServiceFactory = ({
|
||||
const client = new openIdIssuer.Client({
|
||||
client_id: oidcCfg.clientId,
|
||||
client_secret: oidcCfg.clientSecret,
|
||||
redirect_uris: [`${appCfg.SITE_URL}/api/v1/oidc/callback`]
|
||||
redirect_uris: [`${appCfg.SITE_URL}/api/v1/sso/oidc/callback`]
|
||||
});
|
||||
|
||||
const strategy = new OpenIdStrategy(
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useRouter } from "next/router";
|
||||
|
||||
import { isLoggedIn } from "@app/reactQuery";
|
||||
|
||||
import { InitialStep, MFAStep, SAMLSSOStep } from "./components";
|
||||
import { InitialStep, MFAStep, SSOStep } from "./components";
|
||||
import { navigateUserToSelectOrg } from "./Login.utils";
|
||||
|
||||
export const Login = () => {
|
||||
@@ -57,7 +57,9 @@ export const Login = () => {
|
||||
/>
|
||||
);
|
||||
case 2:
|
||||
return <SAMLSSOStep setStep={setStep} />;
|
||||
return <SSOStep setStep={setStep} type="SAML" />;
|
||||
case 3:
|
||||
return <SSOStep setStep={setStep} type="OIDC" />;
|
||||
default:
|
||||
return <div />;
|
||||
}
|
||||
|
||||
@@ -40,11 +40,13 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:
|
||||
const { data: serverDetails } = useFetchServerStatus();
|
||||
|
||||
useEffect(() => {
|
||||
if (serverDetails?.samlDefaultOrgSlug){
|
||||
const callbackPort = queryParams.get("callback_port");
|
||||
const redirectUrl = `/api/v1/sso/redirect/saml2/organizations/${serverDetails?.samlDefaultOrgSlug}${callbackPort ? `?callback_port=${callbackPort}` : ""}`
|
||||
router.push(redirectUrl);
|
||||
}
|
||||
if (serverDetails?.samlDefaultOrgSlug) {
|
||||
const callbackPort = queryParams.get("callback_port");
|
||||
const redirectUrl = `/api/v1/sso/redirect/saml2/organizations/${
|
||||
serverDetails?.samlDefaultOrgSlug
|
||||
}${callbackPort ? `?callback_port=${callbackPort}` : ""}`;
|
||||
router.push(redirectUrl);
|
||||
}
|
||||
}, [serverDetails?.samlDefaultOrgSlug]);
|
||||
|
||||
const handleLogin = async (e: FormEvent<HTMLFormElement>) => {
|
||||
@@ -217,6 +219,19 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:
|
||||
Continue with SAML
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mt-2 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={() => {
|
||||
setStep(3);
|
||||
}}
|
||||
leftIcon={<FontAwesomeIcon icon={faLock} className="mr-2" />}
|
||||
className="mx-0 h-10 w-full"
|
||||
>
|
||||
Continue with OIDC
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mt-2 w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
|
||||
<Button
|
||||
colorSchema="primary"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export { SAMLSSOStep } from "./SAMLSSOStep";
|
||||
@@ -5,9 +5,10 @@ import { Button, Input } from "@app/components/v2";
|
||||
|
||||
type Props = {
|
||||
setStep: (step: number) => void;
|
||||
type: "SAML" | "OIDC";
|
||||
};
|
||||
|
||||
export const SAMLSSOStep = ({ setStep }: Props) => {
|
||||
export const SSOStep = ({ setStep, type }: Props) => {
|
||||
const [ssoIdentifier, setSSOIdentifier] = useState("");
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -16,21 +17,27 @@ export const SAMLSSOStep = ({ setStep }: Props) => {
|
||||
const handleSubmission = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
const callbackPort = queryParams.get("callback_port");
|
||||
window.open(
|
||||
`/api/v1/sso/redirect/saml2/organizations/${ssoIdentifier}${
|
||||
callbackPort ? `?callback_port=${callbackPort}` : ""
|
||||
}`
|
||||
);
|
||||
if (type === "SAML") {
|
||||
window.open(
|
||||
`/api/v1/sso/redirect/saml2/organizations/${ssoIdentifier}${
|
||||
callbackPort ? `?callback_port=${callbackPort}` : ""
|
||||
}`
|
||||
);
|
||||
} else {
|
||||
// TODO: Sheen - Add callback support for CLI login
|
||||
window.open(`/api/v1/sso/oidc/login?orgSlug=${ssoIdentifier}`);
|
||||
}
|
||||
|
||||
window.close();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mx-auto w-full max-w-md md:px-6">
|
||||
<p className="mx-auto mb-6 mb-8 flex w-max justify-center bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
|
||||
<p className="mx-auto mb-8 flex w-max justify-center bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
|
||||
What's your organization slug?
|
||||
</p>
|
||||
<form onSubmit={handleSubmission}>
|
||||
<div className="relative mx-auto flex max-h-24 w-1/4 w-full min-w-[20rem] items-center justify-center rounded-lg md:max-h-28 md:min-w-[22rem] lg:w-1/6">
|
||||
<div className="relative mx-auto flex max-h-24 w-full min-w-[20rem] items-center justify-center rounded-lg md:max-h-28 md:min-w-[22rem] lg:w-1/6">
|
||||
<div className="flex max-h-24 w-full items-center justify-center rounded-lg md:max-h-28">
|
||||
<Input
|
||||
value={ssoIdentifier}
|
||||
@@ -44,7 +51,7 @@ export const SAMLSSOStep = ({ setStep }: Props) => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mx-auto mt-4 flex w-1/4 w-full min-w-[20rem] items-center justify-center rounded-md text-center md:min-w-[22rem] lg:w-1/6">
|
||||
<div className="mx-auto mt-4 flex w-full min-w-[20rem] items-center justify-center rounded-md text-center md:min-w-[22rem] lg:w-1/6">
|
||||
<Button
|
||||
type="submit"
|
||||
colorSchema="primary"
|
||||
@@ -52,7 +59,7 @@ export const SAMLSSOStep = ({ setStep }: Props) => {
|
||||
isFullWidth
|
||||
className="h-14"
|
||||
>
|
||||
Continue with SAML
|
||||
Continue with {type}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
1
frontend/src/views/Login/components/SSOStep/index.tsx
Normal file
1
frontend/src/views/Login/components/SSOStep/index.tsx
Normal file
@@ -0,0 +1 @@
|
||||
export { SSOStep } from "./SSOStep";
|
||||
@@ -1,6 +1,6 @@
|
||||
export { InitialStep } from "./InitialStep";
|
||||
export { MFAStep } from "./MFAStep";
|
||||
export { SAMLSSOStep } from "./SAMLSSOStep";
|
||||
export { SSOStep } from "./SSOStep";
|
||||
|
||||
// SSO-specific step
|
||||
export { PasswordStep } from "./PasswordStep";
|
||||
|
||||
Reference in New Issue
Block a user