calcom/pages/auth/sso/[provider].tsx
Deepak Prabhakara 7b65942de2
Feature/sso signup (#1555)
* updated saml-jackson

* if logged in redirect to getting-started page with username in the query param

* fixed issue with mixed up Google login, profile.id is undefined and this is causing the first record to be retrieved instead of the AND query failing

* updated updated saml-jackson

* document PGSSLMODE for Heroku

* tweaks to PGSSLMODE doc

* for self-hosted instance just allow user to signin with any identity (as long as email matches)

* fixed submitting flag

* added username to onboarding flow (if requested during signup)

* added telemetry for google login, saml login, saml config

* check if firstName and lastName are defined

* convert mutation to an async op

* added e2e test to ensure username query param gets picked up during onboarding

* fixed minor typo and added note about configuring Google integration as an Internal app when self-hosting

* cleaned up unnecessary ssr in sso signup routes

* renamed function

* Revert "cleaned up unnecessary ssr in sso signup routes"

This reverts commit 3607ffef79542d8ca4277a64be38d35bd9457960.

* moved client side code to useEffect hook

* - format
- fixed Save button in SAML config component

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-02-02 18:33:27 +00:00

105 lines
2.7 KiB
TypeScript

import { GetServerSidePropsContext } from "next";
import { signIn } from "next-auth/react";
import { useRouter } from "next/router";
import { useEffect } from "react";
import { asStringOrNull } from "@lib/asStringOrNull";
import { getSession } from "@lib/auth";
import prisma from "@lib/prisma";
import { isSAMLLoginEnabled, hostedCal, samlTenantID, samlProductID, samlTenantProduct } from "@lib/saml";
import { inferSSRProps } from "@lib/types/inferSSRProps";
import { ssrInit } from "@server/lib/ssr";
export type SSOProviderPageProps = inferSSRProps<typeof getServerSideProps>;
export default function Provider(props: SSOProviderPageProps) {
const router = useRouter();
useEffect(() => {
if (props.provider === "saml") {
const email = typeof router.query?.email === "string" ? router.query?.email : null;
if (!email) {
router.push("/auth/error?error=" + "Email not provided");
return;
}
if (!props.isSAMLLoginEnabled) {
router.push("/auth/error?error=" + "SAML login not enabled");
return;
}
signIn("saml", {}, { tenant: props.tenant, product: props.product });
} else {
signIn(props.provider);
}
}, []);
return null;
}
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
// get query params and typecast them to string
// (would be even better to assert them instead of typecasting)
const providerParam = asStringOrNull(context.query.provider);
const emailParam = asStringOrNull(context.query.email);
const usernameParam = asStringOrNull(context.query.username);
if (!providerParam) {
throw new Error(`File is not named sso/[provider]`);
}
const { req } = context;
const session = await getSession({ req });
const ssr = await ssrInit(context);
if (session) {
return {
redirect: {
destination: "/getting-started" + (usernameParam ? `?username=${usernameParam}` : ""),
permanent: false,
},
};
}
let error: string | null = null;
let tenant = samlTenantID;
let product = samlProductID;
if (providerParam === "saml" && hostedCal) {
if (!emailParam) {
error = "Email not provided";
} else {
try {
const ret = await samlTenantProduct(prisma, emailParam);
tenant = ret.tenant;
product = ret.product;
} catch (e: any) {
error = e.message;
}
}
}
if (error) {
return {
redirect: {
destination: "/auth/error?error=" + error,
permanent: false,
},
};
}
return {
props: {
trpcState: ssr.dehydrate(),
provider: providerParam,
isSAMLLoginEnabled,
hostedCal,
tenant,
product,
error,
},
};
};