From df51d05c46b40047297ef84bb403930f65305ec9 Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Tue, 18 Jun 2024 02:10:08 +0800 Subject: [PATCH] feat: integrated oidc with sso login --- backend/src/ee/routes/v1/oidc-router.ts | 32 +++++++++---------- .../ee/services/oidc/oidc-config-service.ts | 2 +- frontend/src/views/Login/Login.tsx | 6 ++-- .../components/InitialStep/InitialStep.tsx | 25 ++++++++++++--- .../Login/components/SAMLSSOStep/index.tsx | 1 - .../SAMLSSOStep.tsx => SSOStep/SSOStep.tsx} | 27 ++++++++++------ .../views/Login/components/SSOStep/index.tsx | 1 + frontend/src/views/Login/components/index.tsx | 2 +- 8 files changed, 60 insertions(+), 36 deletions(-) delete mode 100644 frontend/src/views/Login/components/SAMLSSOStep/index.tsx rename frontend/src/views/Login/components/{SAMLSSOStep/SAMLSSOStep.tsx => SSOStep/SSOStep.tsx} (65%) create mode 100644 frontend/src/views/Login/components/SSOStep/index.tsx diff --git a/backend/src/ee/routes/v1/oidc-router.ts b/backend/src/ee/routes/v1/oidc-router.ts index 49d1d5223..00844309d 100644 --- a/backend/src/ee/routes/v1/oidc-router.ts +++ b/backend/src/ee/routes/v1/oidc-router.ts @@ -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({ diff --git a/backend/src/ee/services/oidc/oidc-config-service.ts b/backend/src/ee/services/oidc/oidc-config-service.ts index 323ccb20a..03d74ea16 100644 --- a/backend/src/ee/services/oidc/oidc-config-service.ts +++ b/backend/src/ee/services/oidc/oidc-config-service.ts @@ -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( diff --git a/frontend/src/views/Login/Login.tsx b/frontend/src/views/Login/Login.tsx index 04a24d233..cad207aa8 100644 --- a/frontend/src/views/Login/Login.tsx +++ b/frontend/src/views/Login/Login.tsx @@ -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 ; + return ; + case 3: + return ; default: return
; } diff --git a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx index 6e2c788ae..82bee7eb4 100644 --- a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx +++ b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx @@ -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) => { @@ -217,6 +219,19 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }: Continue with SAML
+
+ +
diff --git a/frontend/src/views/Login/components/SSOStep/index.tsx b/frontend/src/views/Login/components/SSOStep/index.tsx new file mode 100644 index 000000000..e7d80b2c0 --- /dev/null +++ b/frontend/src/views/Login/components/SSOStep/index.tsx @@ -0,0 +1 @@ +export { SSOStep } from "./SSOStep"; diff --git a/frontend/src/views/Login/components/index.tsx b/frontend/src/views/Login/components/index.tsx index 7c55c4acf..296b0503e 100644 --- a/frontend/src/views/Login/components/index.tsx +++ b/frontend/src/views/Login/components/index.tsx @@ -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";