Skip to content

Commit 897c9d6

Browse files
fix(auth): enhance SAML login handling by introducing userId field and updating JWT token structure (#26428)
1 parent c1e5e0a commit 897c9d6

File tree

1 file changed

+24
-2
lines changed

1 file changed

+24
-2
lines changed

packages/features/auth/lib/next-auth-options.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import { dub } from "./dub";
5252
import { validateSamlAccountConversion } from "./samlAccountLinking";
5353
import CalComAdapter from "./next-auth-custom-adapter";
5454
import { verifyPassword } from "./verifyPassword";
55+
import { UserProfile } from "@calcom/types/UserProfile";
5556

5657
type UserWithProfiles = NonNullable<
5758
Awaited<ReturnType<UserRepository["findByEmailAndIncludeProfilesAndPassword"]>>
@@ -274,6 +275,16 @@ export const CalComCredentialsProvider = CredentialsProvider({
274275
});
275276

276277
const providers: Provider[] = [CalComCredentialsProvider, ImpersonationProvider];
278+
type SamlIdpUser = {
279+
id: number;
280+
userId: number;
281+
firstName: string;
282+
lastName: string;
283+
email: string;
284+
name: string;
285+
email_verified: boolean;
286+
profile: UserProfile;
287+
};
277288

278289
if (IS_GOOGLE_LOGIN_ENABLED) {
279290
providers.push(
@@ -356,7 +367,7 @@ if (isSAMLLoginEnabled) {
356367
credentials: {
357368
code: {},
358369
},
359-
async authorize(credentials) {
370+
async authorize(credentials): Promise<SamlIdpUser | null> {
360371
log.debug("CredentialsProvider:saml-idp:authorize", safeStringify({ credentials }));
361372
if (!credentials) {
362373
return null;
@@ -418,7 +429,11 @@ if (isSAMLLoginEnabled) {
418429
}
419430
const [userProfile] = user?.allProfiles ?? [];
420431
return {
432+
// This `id` is actually email as sent by the saml configuration of NameId=email
433+
// Instead of changing it, we introduce a new userId field to the object
434+
// Also, another reason to not touch it is that setting to to user.id starts breaking the saml-idp flow with an uncaught error something related to that it is expected to be a string
421435
id: id as unknown as number,
436+
userId: user.id,
422437
firstName,
423438
lastName,
424439
email,
@@ -622,7 +637,14 @@ export const getOptions = ({
622637
log.debug("callbacks:jwt:accountType:credentials", safeStringify({ account }));
623638
// return token if credentials,saml-idp
624639
if (account.provider === "saml-idp") {
625-
return { ...token, upId: user.profile?.upId ?? token.upId ?? null } as JWT;
640+
const samlIdpUser = user as SamlIdpUser;
641+
const updatedToken = {
642+
...token,
643+
// Server Session explicitly requires sub to be userId. So, override what is set by BoxyHQ
644+
sub: samlIdpUser.userId.toString(),
645+
upId: samlIdpUser.profile?.upId ?? token.upId ?? null,
646+
} as JWT;
647+
return updatedToken;
626648
}
627649
// any other credentials, add user info
628650
return {

0 commit comments

Comments
 (0)