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 (
+
+ );
+ }
+
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;