diff --git a/apps/builder/src/components/logos/KeycloakLogo.tsx b/apps/builder/src/components/logos/KeycloakLogo.tsx
new file mode 100644
index 00000000000..bfa68202f0e
--- /dev/null
+++ b/apps/builder/src/components/logos/KeycloakLogo.tsx
@@ -0,0 +1,11 @@
+import { IconProps, Icon } from '@chakra-ui/react'
+
+export const KeycloackLogo = (props: IconProps) => (
+
+
+
+
+)
diff --git a/apps/builder/src/features/auth/components/SocialLoginButtons.tsx b/apps/builder/src/features/auth/components/SocialLoginButtons.tsx
index 662398c8502..db627552a8b 100644
--- a/apps/builder/src/features/auth/components/SocialLoginButtons.tsx
+++ b/apps/builder/src/features/auth/components/SocialLoginButtons.tsx
@@ -16,6 +16,7 @@ import { AzureAdLogo } from '@/components/logos/AzureAdLogo'
import { FacebookLogo } from '@/components/logos/FacebookLogo'
import { GitlabLogo } from '@/components/logos/GitlabLogo'
import { useTranslate } from '@tolgee/react'
+import { KeycloackLogo } from '@/components/logos/KeycloakLogo'
type Props = {
providers:
@@ -52,6 +53,8 @@ export const SocialLoginButtons = ({ providers }: Props) => {
const handleCustomOAuthClick = () => handleSignIn('custom-oauth')
+ const handleKeyCloackClick = () => handleSignIn('keycloak')
+
return (
{providers?.github && (
@@ -142,6 +145,20 @@ export const SocialLoginButtons = ({ providers }: Props) => {
})}
)}
+ {providers?.keycloak && (
+ }
+ onClick={handleKeyCloackClick}
+ data-testid="keycloak"
+ isLoading={
+ ['loading', 'authenticated'].includes(status) ||
+ authLoading === 'keycloak'
+ }
+ variant="outline"
+ >
+ {t('auth.socialLogin.keycloakButton.label')}
+
+ )}
)
}
diff --git a/apps/builder/src/i18n/de.json b/apps/builder/src/i18n/de.json
index 6a91e876df2..b910a7606b8 100644
--- a/apps/builder/src/i18n/de.json
+++ b/apps/builder/src/i18n/de.json
@@ -60,6 +60,7 @@
"auth.socialLogin.githubButton.label": "Mit GitHub fortfahren",
"auth.socialLogin.gitlabButton.label": "Mit {gitlabProviderName} fortfahren",
"auth.socialLogin.googleButton.label": "Mit Google fortfahren",
+ "auth.socialLogin.keycloakButton.label": "Mit Keycloak fortfahren",
"back": "Zurück",
"billing.billingPortalButton.label": "Abrechnungsportal",
"billing.contribution.link": "Erfahre mehr.",
diff --git a/apps/builder/src/i18n/en.json b/apps/builder/src/i18n/en.json
index 1d8e3ff093e..212ad7c1627 100644
--- a/apps/builder/src/i18n/en.json
+++ b/apps/builder/src/i18n/en.json
@@ -61,6 +61,7 @@
"auth.socialLogin.githubButton.label": "Continue with GitHub",
"auth.socialLogin.gitlabButton.label": "Continue with {gitlabProviderName}",
"auth.socialLogin.googleButton.label": "Continue with Google",
+ "auth.socialLogin.keycloakButton.label": "Continue with Keycloak",
"back": "Back",
"billing.billingPortalButton.label": "Billing portal",
"billing.contribution.link": "Learn more.",
diff --git a/apps/builder/src/i18n/es.json b/apps/builder/src/i18n/es.json
index 0365655dcff..8c81d5f21b5 100644
--- a/apps/builder/src/i18n/es.json
+++ b/apps/builder/src/i18n/es.json
@@ -60,6 +60,7 @@
"auth.socialLogin.githubButton.label": "Continuar con GitHub",
"auth.socialLogin.gitlabButton.label": "Continuar con {gitlabProviderName}",
"auth.socialLogin.googleButton.label": "Continuar con Google",
+ "auth.socialLogin.keycloakButton.label": "Continuar con Keycloak",
"back": "Volver",
"billing.billingPortalButton.label": "Portal de facturación",
"billing.contribution.link": "Más información.",
diff --git a/apps/builder/src/i18n/fr.json b/apps/builder/src/i18n/fr.json
index 8ab91662283..e670c1d591c 100644
--- a/apps/builder/src/i18n/fr.json
+++ b/apps/builder/src/i18n/fr.json
@@ -61,6 +61,7 @@
"auth.socialLogin.githubButton.label": "Continuer avec GitHub",
"auth.socialLogin.gitlabButton.label": "Continuer avec {gitlabProviderName}",
"auth.socialLogin.googleButton.label": "Continuer avec Google",
+ "auth.socialLogin.keycloakButton.label": "Continuer avec Keycloak",
"back": "Retour",
"billing.billingPortalButton.label": "Portail de facturation",
"billing.contribution.link": "En savoir plus.",
diff --git a/apps/builder/src/i18n/it.json b/apps/builder/src/i18n/it.json
index e3ff66229da..406cff90e4d 100644
--- a/apps/builder/src/i18n/it.json
+++ b/apps/builder/src/i18n/it.json
@@ -61,6 +61,7 @@
"auth.socialLogin.githubButton.label": "Continua con GitHub",
"auth.socialLogin.gitlabButton.label": "Continuare con {gitlabProviderName}",
"auth.socialLogin.googleButton.label": "Continua con Google",
+ "auth.socialLogin.keycloakButton.label": "Continua con Keycloak",
"back": "Indietro",
"billing.billingPortalButton.label": "Portale di fatturazione",
"billing.contribution.link": "Per saperne di più.",
diff --git a/apps/builder/src/i18n/pt-BR.json b/apps/builder/src/i18n/pt-BR.json
index db048e89a34..3c331443583 100644
--- a/apps/builder/src/i18n/pt-BR.json
+++ b/apps/builder/src/i18n/pt-BR.json
@@ -61,6 +61,7 @@
"auth.socialLogin.githubButton.label": "Continuar com GitHub",
"auth.socialLogin.gitlabButton.label": "Continuar com {gitlabProviderName}",
"auth.socialLogin.googleButton.label": "Continuar com Google",
+ "auth.socialLogin.keycloakButton.label": "Continuar com Keycloak",
"back": "Voltar",
"billing.billingPortalButton.label": "Portal de cobrança",
"billing.contribution.link": "Saiba mais.",
diff --git a/apps/builder/src/i18n/pt.json b/apps/builder/src/i18n/pt.json
index 6878de5d545..f13001412a4 100644
--- a/apps/builder/src/i18n/pt.json
+++ b/apps/builder/src/i18n/pt.json
@@ -61,6 +61,7 @@
"auth.socialLogin.githubButton.label": "Continuar com GitHub",
"auth.socialLogin.gitlabButton.label": "Continuar com {gitlabProviderName}",
"auth.socialLogin.googleButton.label": "Continuar com Google",
+ "auth.socialLogin.keycloakButton.label": "Continuar com Keycloak",
"back": "Voltar",
"billing.billingPortalButton.label": "Portal de facturação",
"billing.contribution.link": "Saiba mais.",
diff --git a/apps/builder/src/i18n/ro.json b/apps/builder/src/i18n/ro.json
index 8929a0e9617..25354f8596b 100644
--- a/apps/builder/src/i18n/ro.json
+++ b/apps/builder/src/i18n/ro.json
@@ -60,6 +60,7 @@
"auth.socialLogin.githubButton.label": "Continuați cu GitHub",
"auth.socialLogin.gitlabButton.label": "Continuați cu {customProviderName}",
"auth.socialLogin.googleButton.label": "Continuați cu Google",
+ "auth.socialLogin.keycloakButton.label": "Continuați cu Keycloak",
"back": "Înapoi",
"billing.billingPortalButton.label": "Portalul de facturare",
"billing.contribution.link": "Află mai multe.",
diff --git a/apps/builder/src/pages/api/auth/[...nextauth].ts b/apps/builder/src/pages/api/auth/[...nextauth].ts
index f7f145200e8..09451fb318e 100644
--- a/apps/builder/src/pages/api/auth/[...nextauth].ts
+++ b/apps/builder/src/pages/api/auth/[...nextauth].ts
@@ -5,6 +5,7 @@ import GitlabProvider from 'next-auth/providers/gitlab'
import GoogleProvider from 'next-auth/providers/google'
import FacebookProvider from 'next-auth/providers/facebook'
import AzureADProvider from 'next-auth/providers/azure-ad'
+import KeycloakProvider from 'next-auth/providers/keycloak'
import prisma from '@typebot.io/lib/prisma'
import { Provider } from 'next-auth/providers'
import { NextApiRequest, NextApiResponse } from 'next'
@@ -102,6 +103,21 @@ if (
)
}
+if (
+ env.KEYCLOAK_CLIENT_ID &&
+ env.KEYCLOAK_BASE_URL &&
+ env.KEYCLOAK_CLIENT_SECRET &&
+ env.KEYCLOAK_REALM
+) {
+ providers.push(
+ KeycloakProvider({
+ clientId: env.KEYCLOAK_CLIENT_ID,
+ clientSecret: env.KEYCLOAK_CLIENT_SECRET,
+ issuer: `${env.KEYCLOAK_BASE_URL}/${env.KEYCLOAK_REALM}`,
+ })
+ )
+}
+
if (env.CUSTOM_OAUTH_WELL_KNOWN_URL) {
providers.push({
id: 'custom-oauth',
diff --git a/apps/docs/self-hosting/configuration.mdx b/apps/docs/self-hosting/configuration.mdx
index 0e3eb4ce38b..e8cc682cc03 100644
--- a/apps/docs/self-hosting/configuration.mdx
+++ b/apps/docs/self-hosting/configuration.mdx
@@ -169,6 +169,20 @@ The Authorization callback URL should be `$NEXTAUTH_URL/api/auth/callback/azure-
| AZURE_AD_CLIENT_SECRET | | Application client secret. Can be obtained from Azure Portal. |
| AZURE_AD_TENANT_ID | | Azure Tenant ID |
+## Keycloak (Auth)
+
+Used for authenticating with Keycloak.
+Follow the official Keycloak guide for creating OAuth2 applications [here](https://www.keycloak.org/).
+
+| Parameter | Default | Description |
+| ------------------------ | ------------------ | ------------------------------------------------------------------------------------ |
+| KEYCLOAK_CLIENT_ID | | Application client ID. |
+| KEYCLOAK_CLIENT_SECRET | | Application secret |
+| KEYCLOAK_REALM | | Your Keycloak Realm |
+| KEYCLOAK_BASE_URL | | Base URL of the Keycloak instance |
+
+
+
## Custom OAuth Provider (Auth)
| Parameter | Default | Description |
diff --git a/packages/env/env.ts b/packages/env/env.ts
index e68a087a44a..df36c2d45a2 100644
--- a/packages/env/env.ts
+++ b/packages/env/env.ts
@@ -404,6 +404,15 @@ const tolgeeEnv = {
},
}
+const keycloakEnv = {
+ server: {
+ KEYCLOAK_CLIENT_ID: z.string().min(1).optional(),
+ KEYCLOAK_CLIENT_SECRET: z.string().min(1).optional(),
+ KEYCLOAK_REALM: z.string().min(1).optional(),
+ KEYCLOAK_BASE_URL: z.string().url().optional(),
+ },
+}
+
export const env = createEnv({
server: {
...baseEnv.server,
@@ -422,6 +431,7 @@ export const env = createEnv({
...customOAuthEnv.server,
...sentryEnv.server,
...telemetryEnv.server,
+ ...keycloakEnv.server
},
client: {
...baseEnv.client,