diff --git a/backend/src/ee/routes/v1/oidc-router.ts b/backend/src/ee/routes/v1/oidc-router.ts index c5433c008..55d3be19d 100644 --- a/backend/src/ee/routes/v1/oidc-router.ts +++ b/backend/src/ee/routes/v1/oidc-router.ts @@ -45,14 +45,20 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => { method: "GET", schema: { querystring: z.object({ - orgSlug: z.string().trim() + orgSlug: z.string().trim(), + callbackPort: z.string().trim().optional() }) }, handler: async (req, res) => { // get params, save to session - const { orgSlug } = req.query; + const { orgSlug, callbackPort } = req.query; req.session.set("oidcOrgSlug", orgSlug); - const oidcStrategy = await server.services.oidc.getOrgAuthStrategy(orgSlug); + + if (callbackPort) { + req.session.set("callbackPort", callbackPort); + } + + const oidcStrategy = await server.services.oidc.getOrgAuthStrategy(orgSlug, callbackPort); ( passport.authenticate(oidcStrategy as Strategy, { scope: "profile email openid" @@ -67,7 +73,9 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => { method: "GET", handler: async (req, res) => { const oidcOrgSlug = req.session.get("oidcOrgSlug"); - const oidcStrategy = await server.services.oidc.getOrgAuthStrategy(oidcOrgSlug); + const callbackPort = req.session.get("callbackPort"); + const oidcStrategy = await server.services.oidc.getOrgAuthStrategy(oidcOrgSlug, callbackPort); + await ( passport.authenticate(oidcStrategy as Strategy, { failureRedirect: "/api/v1/sso/oidc/login/error", @@ -76,6 +84,8 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => { }) as any )(req, res); + await req.session.destroy(); + if (req.passportUser.isUserCompleted) { return res.redirect( `http://localhost:8080/login/sso?token=${encodeURIComponent(req.passportUser.providerAuthToken)}` @@ -92,7 +102,9 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => { server.route({ url: "/login/error", method: "GET", - handler: (req, res) => { + handler: async (req, res) => { + await req.session.destroy(); + return res.status(500).send({ error: "Authentication error", details: req.query diff --git a/backend/src/ee/services/oidc/oidc-config-service.ts b/backend/src/ee/services/oidc/oidc-config-service.ts index 03d74ea16..b880c8664 100644 --- a/backend/src/ee/services/oidc/oidc-config-service.ts +++ b/backend/src/ee/services/oidc/oidc-config-service.ts @@ -63,7 +63,7 @@ export const oidcConfigServiceFactory = ({ smtpService, oidcConfigDAL }: TOidcConfigServiceFactoryDep) => { - const oidcLogin = async ({ externalId, email, firstName, lastName, orgId }: TOidcLoginDTO) => { + const oidcLogin = async ({ externalId, email, firstName, lastName, orgId, callbackPort }: TOidcLoginDTO) => { const appCfg = getConfig(); const userAlias = await userAliasDAL.findOne({ externalId, @@ -188,7 +188,8 @@ export const oidcConfigServiceFactory = ({ organizationSlug: organization.slug, authMethod: AuthMethod.OIDC, authType: UserAliasType.OIDC, - isUserCompleted + isUserCompleted, + ...(callbackPort && { callbackPort }) }, appCfg.AUTH_SECRET, { @@ -491,7 +492,7 @@ export const oidcConfigServiceFactory = ({ return oidcCfg; }; - const getOrgAuthStrategy = async (orgSlug: string) => { + const getOrgAuthStrategy = async (orgSlug: string, callbackPort?: string) => { const appCfg = getConfig(); const org = await orgDAL.findOne({ @@ -542,7 +543,8 @@ export const oidcConfigServiceFactory = ({ externalId: claims.sub, firstName: claims.given_name ?? "", lastName: claims.family_name ?? "", - orgId: org.id + orgId: org.id, + callbackPort }) .then(({ isUserCompleted, providerAuthToken }) => { cb(null, { isUserCompleted, providerAuthToken }); diff --git a/backend/src/ee/services/oidc/oidc-config-types.ts b/backend/src/ee/services/oidc/oidc-config-types.ts index a160b272a..4c729ceea 100644 --- a/backend/src/ee/services/oidc/oidc-config-types.ts +++ b/backend/src/ee/services/oidc/oidc-config-types.ts @@ -6,6 +6,7 @@ export type TOidcLoginDTO = { firstName: string; lastName?: string; orgId: string; + callbackPort?: string; }; export type TGetOidcCfgDTO = diff --git a/frontend/src/views/Login/components/SSOStep/SSOStep.tsx b/frontend/src/views/Login/components/SSOStep/SSOStep.tsx index 5e70cf1a7..9663c04a9 100644 --- a/frontend/src/views/Login/components/SSOStep/SSOStep.tsx +++ b/frontend/src/views/Login/components/SSOStep/SSOStep.tsx @@ -24,8 +24,11 @@ export const SSOStep = ({ setStep, type }: Props) => { }` ); } else { - // TODO: Sheen - Add callback support for CLI login - window.open(`/api/v1/sso/oidc/login?orgSlug=${ssoIdentifier}`); + window.open( + `/api/v1/sso/oidc/login?orgSlug=${ssoIdentifier}${ + callbackPort ? `&callbackPort=${callbackPort}` : "" + }` + ); } window.close();