diff --git a/.env b/.env index 6745e653049..5cc0db4e854 100644 --- a/.env +++ b/.env @@ -29,13 +29,15 @@ OPENID_CONFIG=`{ "PROVIDER_URL": "", "CLIENT_ID": "", "CLIENT_SECRET": "", - "SCOPES": "" + "SCOPES": "", + "NAME_CLAIM": "" }` # /!\ legacy openid settings, prefer the config above OPENID_CLIENT_ID= OPENID_CLIENT_SECRET= OPENID_SCOPES="openid profile" # Add "email" for some providers like Google that do not provide preferred_username +OPENID_NAME_CLAIM="name" # Change to "username" for some providers that do not provide name OPENID_PROVIDER_URL=https://huggingface.co # for Google, use https://accounts.google.com OPENID_TOLERANCE= OPENID_RESOURCE= diff --git a/src/lib/server/auth.ts b/src/lib/server/auth.ts index 50ab3fdb4c3..96e6ec8f345 100644 --- a/src/lib/server/auth.ts +++ b/src/lib/server/auth.ts @@ -6,6 +6,7 @@ import { OPENID_CLIENT_SECRET, OPENID_PROVIDER_URL, OPENID_SCOPES, + OPENID_NAME_CLAIM, OPENID_TOLERANCE, OPENID_RESOURCE, OPENID_CONFIG, @@ -32,12 +33,16 @@ const stringWithDefault = (value: string) => .default(value) .transform((el) => (el ? el : value)); -const OIDConfig = z +export const OIDConfig = z .object({ CLIENT_ID: stringWithDefault(OPENID_CLIENT_ID), CLIENT_SECRET: stringWithDefault(OPENID_CLIENT_SECRET), PROVIDER_URL: stringWithDefault(OPENID_PROVIDER_URL), SCOPES: stringWithDefault(OPENID_SCOPES), + NAME_CLAIM: stringWithDefault(OPENID_NAME_CLAIM).refine( + (el) => !["preferred_username", "email", "picture", "sub"].includes(el), + { message: "nameClaim cannot be one of the restricted keys." } + ), TOLERANCE: stringWithDefault(OPENID_TOLERANCE), RESOURCE: stringWithDefault(OPENID_RESOURCE), }) diff --git a/src/routes/login/callback/updateUser.ts b/src/routes/login/callback/updateUser.ts index f2fac350531..90b83116121 100644 --- a/src/routes/login/callback/updateUser.ts +++ b/src/routes/login/callback/updateUser.ts @@ -8,6 +8,7 @@ import { error, type Cookies } from "@sveltejs/kit"; import crypto from "crypto"; import { sha256 } from "$lib/utils/sha256"; import { addWeeks } from "date-fns"; +import { OIDConfig } from "$lib/server/auth"; export async function updateUser(params: { userData: UserinfoResponse; @@ -38,10 +39,24 @@ export async function updateUser(params: { sub: z.string(), email: z.string().email().optional(), }) + .setKey(OIDConfig.NAME_CLAIM, z.string()) .refine((data) => data.preferred_username || data.email, { message: "Either preferred_username or email must be provided by the provider.", }) - .parse(userData); + .transform((data) => ({ + ...data, + name: data[OIDConfig.NAME_CLAIM], + })) + .parse(userData) as { + preferred_username?: string; + email?: string; + picture?: string; + sub: string; + name: string; + } & Record; + + // Dynamically access user data based on NAME_CLAIM from environment + // This approach allows us to adapt to different OIDC providers flexibly. // check if user already exists const existingUser = await collections.users.findOne({ hfUserId });