diff --git a/frontend/__tests__/components/features/auth/login-content.test.tsx b/frontend/__tests__/components/features/auth/login-content.test.tsx
index efedb93164..a331ee2378 100644
--- a/frontend/__tests__/components/features/auth/login-content.test.tsx
+++ b/frontend/__tests__/components/features/auth/login-content.test.tsx
@@ -15,6 +15,7 @@ vi.mock("#/hooks/use-auth-url", () => ({
bitbucket: "https://bitbucket.org/site/oauth2/authorize",
bitbucket_data_center:
"https://bitbucket-dc.example.com/site/oauth2/authorize",
+ enterprise_sso: "https://auth.example.com/realms/test/protocol/openid-connect/auth",
};
if (config.appMode === "saas") {
return urls[config.identityProvider] || null;
@@ -117,6 +118,74 @@ describe("LoginContent", () => {
).not.toBeInTheDocument();
});
+ it("should display Enterprise SSO button when configured", () => {
+ render(
+
+
+ ,
+ );
+
+ expect(
+ screen.getByRole("button", { name: /ENTERPRISE_SSO\$CONNECT_TO_ENTERPRISE_SSO/i }),
+ ).toBeInTheDocument();
+ });
+
+ it("should display Enterprise SSO alongside other providers when all configured", () => {
+ render(
+
+
+ ,
+ );
+
+ expect(
+ screen.getByRole("button", { name: "GITHUB$CONNECT_TO_GITHUB" }),
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole("button", { name: "GITLAB$CONNECT_TO_GITLAB" }),
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole("button", { name: /BITBUCKET\$CONNECT_TO_BITBUCKET/i }),
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole("button", { name: /ENTERPRISE_SSO\$CONNECT_TO_ENTERPRISE_SSO/i }),
+ ).toBeInTheDocument();
+ });
+
+ it("should redirect to Enterprise SSO auth URL when Enterprise SSO button is clicked", async () => {
+ const user = userEvent.setup();
+ const mockUrl = "https://auth.example.com/realms/test/protocol/openid-connect/auth";
+
+ render(
+
+
+ ,
+ );
+
+ const enterpriseSsoButton = screen.getByRole("button", {
+ name: /ENTERPRISE_SSO\$CONNECT_TO_ENTERPRISE_SSO/i,
+ });
+ await user.click(enterpriseSsoButton);
+
+ await waitFor(() => {
+ expect(window.location.href).toContain(mockUrl);
+ });
+ });
+
it("should display message when no providers are configured", () => {
render(
diff --git a/frontend/src/components/features/auth/login-content.tsx b/frontend/src/components/features/auth/login-content.tsx
index 30da67c301..fbae5df4ea 100644
--- a/frontend/src/components/features/auth/login-content.tsx
+++ b/frontend/src/components/features/auth/login-content.tsx
@@ -1,4 +1,5 @@
import { useTranslation } from "react-i18next";
+import { FaUserShield } from "react-icons/fa";
import { I18nKey } from "#/i18n/declaration";
import OpenHandsLogoWhite from "#/assets/branding/openhands-logo-white.svg?react";
import GitHubLogo from "#/assets/branding/github-logo.svg?react";
@@ -65,6 +66,12 @@ export function LoginContent({
authUrl,
});
+ const enterpriseSsoAuthUrl = useAuthUrl({
+ appMode: appMode || null,
+ identityProvider: "enterprise_sso",
+ authUrl,
+ });
+
const handleAuthRedirect = async (
redirectUrl: string,
provider: Provider,
@@ -127,6 +134,12 @@ export function LoginContent({
}
};
+ const handleEnterpriseSsoAuth = () => {
+ if (enterpriseSsoAuthUrl) {
+ handleAuthRedirect(enterpriseSsoAuthUrl, "enterprise_sso");
+ }
+ };
+
const showGithub =
providersConfigured &&
providersConfigured.length > 0 &&
@@ -143,6 +156,10 @@ export function LoginContent({
providersConfigured &&
providersConfigured.length > 0 &&
providersConfigured.includes("bitbucket_data_center");
+ const showEnterpriseSso =
+ providersConfigured &&
+ providersConfigured.length > 0 &&
+ providersConfigured.includes("enterprise_sso");
const noProvidersConfigured =
!providersConfigured || providersConfigured.length === 0;
@@ -261,6 +278,19 @@ export function LoginContent({
)}
+
+ {showEnterpriseSso && (
+
+ )}
>
)}