diff --git a/.env.example b/.env.example index 4e220d6..2f3a864 100644 --- a/.env.example +++ b/.env.example @@ -96,3 +96,24 @@ NUXT_PUBLIC_SITE_URL=http://localhost:3000 # Display name for the SSO button (default: "SSO") # OIDC_PROVIDER_NAME=Company SSO + +# ─── Optional: Social Sign-In (Google, GitHub, Microsoft) ──────────────────── +# Enable social login buttons on the sign-in and sign-up pages. +# Each provider requires both CLIENT_ID and CLIENT_SECRET to be set. +# When configured, "Continue with " buttons appear on the auth pages. + +# Google — Create credentials at https://console.cloud.google.com/apis/credentials +# Redirect URI: https://yourdomain.com/api/auth/callback/google +# AUTH_GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com +# AUTH_GOOGLE_CLIENT_SECRET=GOCSPX-your-google-client-secret + +# GitHub — Create an OAuth App at https://github.com/settings/developers +# Redirect URI: https://yourdomain.com/api/auth/callback/github +# AUTH_GITHUB_CLIENT_ID=your-github-client-id +# AUTH_GITHUB_CLIENT_SECRET=your-github-client-secret + +# Microsoft — Register an app at https://portal.azure.com → App registrations +# Redirect URI: https://yourdomain.com/api/auth/callback/microsoft +# AUTH_MICROSOFT_CLIENT_ID=your-microsoft-client-id +# AUTH_MICROSOFT_CLIENT_SECRET=your-microsoft-client-secret +# AUTH_MICROSOFT_TENANT_ID=common diff --git a/app/pages/auth/sign-in.vue b/app/pages/auth/sign-in.vue index fa3732b..0f24f55 100644 --- a/app/pages/auth/sign-in.vue +++ b/app/pages/auth/sign-in.vue @@ -16,16 +16,27 @@ const email = ref(""); const password = ref(""); const error = ref(""); const isLoading = ref(false); +const socialLoading = ref(null); const ssoRedirecting = ref(false); const route = useRoute(); const config = useRuntimeConfig(); const localePath = useLocalePath(); const { track } = useTrack(); -const oidcEnabled = computed(() => config.public.oidcEnabled as boolean); + +const { data: authProviders } = await useFetch('/api/auth/providers'); +const oidcEnabled = computed(() => authProviders.value?.oidc ?? false); const oidcProviderName = computed( - () => (config.public.oidcProviderName as string) || "SSO", + () => authProviders.value?.oidcProviderName || "SSO", ); +const socialProviders = computed(() => { + const providers: { id: string; name: string }[] = []; + if (authProviders.value?.google) providers.push({ id: "google", name: "Google" }); + if (authProviders.value?.github) providers.push({ id: "github", name: "GitHub" }); + if (authProviders.value?.microsoft) providers.push({ id: "microsoft", name: "Microsoft" }); + return providers; +}); + onMounted(() => track("signin_page_viewed")); if (route.query.live === "1") { @@ -163,6 +174,31 @@ async function handleEnterpriseSso() { ssoRedirecting.value = false; } } + +/** + * Social sign-in — Google, GitHub, Microsoft. + * Uses better-auth's built-in signIn.social() which handles the full OAuth redirect flow. + */ +async function handleSocialSignIn(providerId: string) { + socialLoading.value = providerId; + error.value = ""; + const pendingInvitation = route.query.invitation as string | undefined; + const callbackURL = pendingInvitation + ? localePath(`/auth/accept-invitation/${pendingInvitation}`) + : localePath("/dashboard"); + try { + await authClient.signIn.social({ + provider: providerId as "google" | "github" | "microsoft", + callbackURL, + }); + } catch (e: unknown) { + error.value = + e instanceof Error + ? e.message + : "Social sign-in failed. Please try again."; + socialLoading.value = null; + } +}