From 3e4a7d3638e5225303dd9de379ab2610f1da89c5 Mon Sep 17 00:00:00 2001 From: Bryan Frimin Date: Sun, 22 Mar 2026 10:41:41 +0100 Subject: [PATCH] Add OIDC login support to compliance page Add Google and Microsoft sign-in buttons to the trust center connect page, matching the console sign-in experience. The backend OIDC flow already supports flexible continue URLs, so only the GraphQL schema and frontend needed changes. Signed-off-by: Bryan Frimin --- apps/trust/src/pages/auth/ConnectPage.tsx | 83 ++++++++++++++++++++++- pkg/server/api/trust/v1/schema.graphql | 8 +++ pkg/server/api/trust/v1/v1_resolver.go | 17 +++++ 3 files changed, 105 insertions(+), 3 deletions(-) diff --git a/apps/trust/src/pages/auth/ConnectPage.tsx b/apps/trust/src/pages/auth/ConnectPage.tsx index 0ff7c9ff8..b003dbae5 100644 --- a/apps/trust/src/pages/auth/ConnectPage.tsx +++ b/apps/trust/src/pages/auth/ConnectPage.tsx @@ -1,10 +1,11 @@ import type { GraphQLError } from "@probo/helpers"; import { usePageTitle } from "@probo/hooks"; import { useTranslate } from "@probo/i18n"; -import { Button, Field, useToast } from "@probo/ui"; -import { useEffect, useRef, useState } from "react"; +import { Button, Field, Google, Microsoft, useToast } from "@probo/ui"; +import { type ComponentProps, Suspense, useEffect, useRef, useState } from "react"; import { type PreloadedQuery, + useLazyLoadQuery, useMutation, usePreloadedQuery, } from "react-relay"; @@ -16,6 +17,7 @@ import { useFormWithSchema } from "#/hooks/useFormWithSchema"; import { getPathPrefix } from "#/utils/pathPrefix"; import type { ConnectPageMutation, SendMagicLinkInput } from "./__generated__/ConnectPageMutation.graphql"; +import type { ConnectPageOIDCQuery } from "./__generated__/ConnectPageOIDCQuery.graphql"; import type { ConnectPageQuery } from "./__generated__/ConnectPageQuery.graphql"; export const connectPageQuery = graphql` @@ -28,6 +30,15 @@ export const connectPageQuery = graphql` } `; +const oidcProvidersQuery = graphql` + query ConnectPageOIDCQuery { + oidcProviders { + name + loginURL + } + } +`; + const sendMagicLinkMutation = graphql` mutation ConnectPageMutation($input: SendMagicLinkInput!) { sendMagicLink(input: $input) { @@ -36,6 +47,14 @@ const sendMagicLinkMutation = graphql` } `; +const providerIcons: Record< + string, + (props: ComponentProps<"svg">) => React.ReactNode +> = { + google: Google, + microsoft: Microsoft, +}; + const schema = z.object({ email: z.string().email(), }); @@ -44,6 +63,58 @@ type FormData = z.infer; const timerDurationSeconds = 60; +function Divider({ children }: { children: React.ReactNode }) { + return ( +
+
+ + {children} + +
+ ); +} + +function OIDCButtons({ safeContinueUrl }: { safeContinueUrl: string }) { + const { __ } = useTranslate(); + + const data = useLazyLoadQuery(oidcProvidersQuery, {}); + + if (data.oidcProviders.length === 0) { + return null; + } + + const continueUrl = new URL(safeContinueUrl); + + return ( + <> + {data.oidcProviders.map((provider) => { + const Icon = providerIcons[provider.name]; + return ( + + ); + })} + {__("Or")} + + ); +} + export function ConnectPage(props: { queryRef: PreloadedQuery; }) { @@ -164,11 +235,17 @@ export function ConnectPage(props: {

{__( - "Enter your email address to connect with a magic link and start requesting access to documents", + "Sign in to start requesting access to documents", )}

+
+ + + +
+
void handleSubmit(e)} className="space-y-6">