From 3a6a9c7df2f66baa63290edea67ab2c2bcc22062 Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 22 Jun 2026 12:08:46 -0400 Subject: [PATCH] feat: oauth autoredirect support --- docs/CONFIGURATION.md | 4 ++++ src/env.ts | 2 ++ src/pages/auth/signin.tsx | 13 ++++++++++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 5fc723d6..5f18c0e4 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -67,6 +67,10 @@ Used for magic-link login and invites. ### OAuth providers +#### Shared OAuth settings + +- `OAUTH_AUTO_REDIRECT`: Optional flag. When set to `true`, the sign-in page automatically redirects to the first configured OAuth provider. This applies to any configured OAuth provider, including Google, Authentik, Keycloak, and generic OIDC. + #### Google - `GOOGLE_CLIENT_ID` diff --git a/src/env.ts b/src/env.ts index 516381af..b7600844 100644 --- a/src/env.ts +++ b/src/env.ts @@ -71,6 +71,7 @@ export const env = createEnv({ OIDC_CLIENT_SECRET: z.string().optional(), OIDC_WELL_KNOWN_URL: z.string().optional(), OIDC_ALLOW_DANGEROUS_EMAIL_LINKING: z.boolean().optional(), + OAUTH_AUTO_REDIRECT: z.boolean().optional(), UPLOAD_MAX_FILE_SIZE_MB: z.coerce.number().int().positive().default(10), }, @@ -140,6 +141,7 @@ export const env = createEnv({ OIDC_CLIENT_SECRET: process.env.OIDC_CLIENT_SECRET, OIDC_WELL_KNOWN_URL: process.env.OIDC_WELL_KNOWN_URL, OIDC_ALLOW_DANGEROUS_EMAIL_LINKING: Boolean(process.env.OIDC_ALLOW_DANGEROUS_EMAIL_LINKING), + OAUTH_AUTO_REDIRECT: 'true' === process.env.OAUTH_AUTO_REDIRECT, UPLOAD_MAX_FILE_SIZE_MB: process.env.UPLOAD_MAX_FILE_SIZE_MB ? Number(process.env.UPLOAD_MAX_FILE_SIZE_MB) : 10, diff --git a/src/pages/auth/signin.tsx b/src/pages/auth/signin.tsx index 35490494..c5e9e49c 100644 --- a/src/pages/auth/signin.tsx +++ b/src/pages/auth/signin.tsx @@ -59,7 +59,8 @@ const Home: NextPage<{ feedbackEmail: string; providers: ClientSafeProvider[]; callbackUrl?: string; -}> = ({ error, providers: serverProviders, feedbackEmail, callbackUrl }) => { + oauthAutoRedirect: boolean; +}> = ({ error, providers: serverProviders, feedbackEmail, callbackUrl, oauthAutoRedirect }) => { const { t } = useTranslation(); const [emailStatus, setEmailStatus] = useState<'idle' | 'sending' | 'success'>('idle'); const [showVerificationStep, setShowVerificationStep] = useState(false); @@ -110,6 +111,15 @@ const Home: NextPage<{ } }, [error, t]); + useEffect(() => { + if (oauthAutoRedirect && !showVerificationStep && providers.length > 0 && !isLoadingProviders) { + const oauthProvider = providers.find((provider) => 'oauth' === provider.type); + if (oauthProvider) { + void signIn(oauthProvider.id, { callbackUrl }); + } + } + }, [oauthAutoRedirect, showVerificationStep, providers, isLoadingProviders, callbackUrl]); + const onEmailSubmit = useCallback(async () => { setEmailStatus('sending'); const email = emailForm.getValues().email.toLowerCase(); @@ -293,6 +303,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => { feedbackEmail: env.FEEDBACK_EMAIL ?? '', providers: Object.values(providers ?? {}), callbackUrl: callbackUrl && !Array.isArray(callbackUrl) ? callbackUrl : '', + oauthAutoRedirect: env.OAUTH_AUTO_REDIRECT, }, }; };