fix: SAML SSO - Stop relying on invitedTo column and use membership table instead (#11331)

This commit is contained in:
Kiran K
2023-09-14 14:57:45 +02:00
committed by GitHub
parent bb0574dff8
commit d2b0dd8eab
4 changed files with 62 additions and 44 deletions
+3 -8
View File
@@ -7,13 +7,8 @@ import { getPremiumMonthlyPlanPriceId } from "@calcom/app-store/stripepayment/li
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
import stripe from "@calcom/features/ee/payments/server/stripe";
import {
hostedCal,
isSAMLLoginEnabled,
samlProductID,
samlTenantID,
samlTenantProduct,
} from "@calcom/features/ee/sso/lib/saml";
import { hostedCal, isSAMLLoginEnabled, samlProductID, samlTenantID } from "@calcom/features/ee/sso/lib/saml";
import { ssoTenantProduct } from "@calcom/features/ee/sso/lib/sso";
import { checkUsername } from "@calcom/lib/server/checkUsername";
import prisma from "@calcom/prisma";
@@ -111,7 +106,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
error = "Email not provided";
} else {
try {
const ret = await samlTenantProduct(prisma, emailParam);
const ret = await ssoTenantProduct(prisma, emailParam);
tenant = ret.tenant;
product = ret.product;
} catch (e) {
-34
View File
@@ -2,8 +2,6 @@ import type { SAMLSSORecord, OIDCSSORecord } from "@boxyhq/saml-jackson";
import { HOSTED_CAL_FEATURES } from "@calcom/lib/constants";
import { isTeamAdmin } from "@calcom/lib/server/queries/teams";
import type { PrismaClient } from "@calcom/prisma";
import { TRPCError } from "@calcom/trpc/server";
export const samlDatabaseUrl = process.env.SAML_DATABASE_URL || "";
export const isSAMLLoginEnabled = samlDatabaseUrl.length > 0;
@@ -30,38 +28,6 @@ export const isSAMLAdmin = (email: string) => {
return false;
};
export const samlTenantProduct = async (prisma: PrismaClient, email: string) => {
const user = await prisma.user.findUnique({
where: {
email,
},
select: {
id: true,
invitedTo: true,
},
});
if (!user) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "no_account_exists",
});
}
if (!user.invitedTo) {
throw new TRPCError({
code: "BAD_REQUEST",
message:
"Could not find a SAML Identity Provider for your email. Please contact your admin to ensure you have been given access to Cal",
});
}
return {
tenant: tenantPrefix + user.invitedTo,
product: samlProductID,
};
};
export const canAccess = async (user: { id: number; email: string }, teamId: number | null) => {
const { id: userId, email } = user;
+57
View File
@@ -0,0 +1,57 @@
import type { PrismaClient } from "@calcom/prisma";
import { TRPCError } from "@calcom/trpc/server";
import jackson from "./jackson";
import { tenantPrefix, samlProductID } from "./saml";
export const ssoTenantProduct = async (prisma: PrismaClient, email: string) => {
const { connectionController } = await jackson();
const memberships = await prisma.membership.findMany({
select: {
teamId: true,
},
where: {
accepted: true,
user: {
email,
},
},
});
if (!memberships || memberships.length === 0) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "no_account_exists",
});
}
// Check SSO connections for each team user is a member of
// We'll use the first one we find
const promises = memberships.map(({ teamId }) =>
connectionController.getConnections({
tenant: `${tenantPrefix}${teamId}`,
product: samlProductID,
})
);
const connectionResults = await Promise.allSettled(promises);
const connectionsFound = connectionResults
.filter((result) => result.status === "fulfilled")
.map((result) => (result.status === "fulfilled" ? result.value : []))
.filter((connections) => connections.length > 0);
if (connectionsFound.length === 0) {
throw new TRPCError({
code: "BAD_REQUEST",
message:
"Could not find a SSO Identity Provider for your email. Please contact your admin to ensure you have been given access to Cal",
});
}
return {
tenant: connectionsFound[0][0].tenant,
product: samlProductID,
};
};
@@ -1,4 +1,4 @@
import { samlTenantProduct } from "@calcom/features/ee/sso/lib/saml";
import { ssoTenantProduct } from "@calcom/features/ee/sso/lib/sso";
import type { PrismaClient } from "@calcom/prisma";
import type { TSamlTenantProductInputSchema } from "./samlTenantProduct.schema";
@@ -14,7 +14,7 @@ export const samlTenantProductHandler = ({ ctx, input }: SamlTenantProductOption
const { prisma } = ctx;
const { email } = input;
return samlTenantProduct(prisma, email);
return ssoTenantProduct(prisma, email);
};
export default samlTenantProductHandler;