From 5fe3714edd343e4a44d20841c8f67c445fb69abc Mon Sep 17 00:00:00 2001 From: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com> Date: Wed, 17 Dec 2025 14:00:12 +0100 Subject: [PATCH] feat: auto skip consent screen for trusted oauth clients (#25640) * auto constent for trusted clients * add loading state --------- Co-authored-by: CarinaWolli --- .../modules/auth/oauth2/authorize-view.tsx | 35 ++++++++++++++++--- .../migration.sql | 2 ++ packages/prisma/schema.prisma | 1 + .../routers/viewer/oAuth/getClient.handler.ts | 1 + 4 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 packages/prisma/migrations/20251205111359_add_is_trust_to_o_auth_client/migration.sql diff --git a/apps/web/modules/auth/oauth2/authorize-view.tsx b/apps/web/modules/auth/oauth2/authorize-view.tsx index 1f9ba1505a..332d8e8dda 100644 --- a/apps/web/modules/auth/oauth2/authorize-view.tsx +++ b/apps/web/modules/auth/oauth2/authorize-view.tsx @@ -69,7 +69,9 @@ export default function Authorize() { } if (client?.redirectUri) { - window.location.href = `${client.redirectUri}${client.redirectUri.includes("?") ? "&" : "?"}${errorParams.toString()}`; + window.location.href = `${client.redirectUri}${ + client.redirectUri.includes("?") ? "&" : "?" + }${errorParams.toString()}`; } }, }); @@ -89,6 +91,18 @@ export default function Authorize() { } }, [isPendingProfiles]); + // Auto-authorize trusted clients + useEffect(() => { + if (client?.isTrusted && selectedAccount) { + generateAuthCodeMutation.mutate({ + clientId: client_id as string, + scopes, + codeChallenge: code_challenge || undefined, + codeChallengeMethod: (code_challenge_method as "S256") || undefined, + }); + } + }, [client?.isTrusted, selectedAccount]); + useEffect(() => { if (status === "unauthenticated") { const urlSearchParams = new URLSearchParams({ @@ -108,9 +122,20 @@ export default function Authorize() { return
{t("unauthorized")}
; } + // Don't show UI for trusted clients, they'll auto-authorize + if (client.isTrusted && selectedAccount) { + return ( +
+
+ Authorizing... +
+
+ ); + } + return (
-
+
-

+

{t("access_cal_account", { clientName: client.name, appName: APP_NAME })}

{t("select_account_team")}
@@ -141,7 +166,7 @@ export default function Authorize() { defaultValue={selectedAccount || mappedProfiles[0]} options={mappedProfiles} /> -
{t("allow_client_to", { clientName: client.name })}
+
{t("allow_client_to", { clientName: client.name })}
  • {" "} @@ -166,7 +191,7 @@ export default function Authorize() { {t("access_bookings")}
-
+
diff --git a/packages/prisma/migrations/20251205111359_add_is_trust_to_o_auth_client/migration.sql b/packages/prisma/migrations/20251205111359_add_is_trust_to_o_auth_client/migration.sql new file mode 100644 index 0000000000..29d712b54b --- /dev/null +++ b/packages/prisma/migrations/20251205111359_add_is_trust_to_o_auth_client/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "public"."OAuthClient" ADD COLUMN "isTrusted" BOOLEAN NOT NULL DEFAULT false; diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index cb544bbe9a..cf9cd5e906 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -1765,6 +1765,7 @@ model OAuthClient { clientType OAuthClientType @default(CONFIDENTIAL) name String logo String? + isTrusted Boolean @default(false) accessCodes AccessCode[] } diff --git a/packages/trpc/server/routers/viewer/oAuth/getClient.handler.ts b/packages/trpc/server/routers/viewer/oAuth/getClient.handler.ts index 9a57b8f6d0..2b5119ac18 100644 --- a/packages/trpc/server/routers/viewer/oAuth/getClient.handler.ts +++ b/packages/trpc/server/routers/viewer/oAuth/getClient.handler.ts @@ -18,6 +18,7 @@ export const getClientHandler = async ({ input }: GetClientOptions) => { redirectUri: true, name: true, logo: true, + isTrusted: true, }, }); return client;