Add Enterprise SSO login button to V1 login page (#13390)

Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
chuckbutkus
2026-03-13 16:57:34 -04:00
committed by GitHub
parent f5d0af15d9
commit 873dc6628f
2 changed files with 99 additions and 0 deletions

View File

@@ -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(
<MemoryRouter>
<LoginContent
githubAuthUrl="https://github.com/oauth/authorize"
appMode="saas"
authUrl="https://auth.example.com"
providersConfigured={["enterprise_sso"]}
/>
</MemoryRouter>,
);
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(
<MemoryRouter>
<LoginContent
githubAuthUrl="https://github.com/oauth/authorize"
appMode="saas"
authUrl="https://auth.example.com"
providersConfigured={["github", "gitlab", "bitbucket", "enterprise_sso"]}
/>
</MemoryRouter>,
);
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(
<MemoryRouter>
<LoginContent
githubAuthUrl="https://github.com/oauth/authorize"
appMode="saas"
authUrl="https://auth.example.com"
providersConfigured={["enterprise_sso"]}
/>
</MemoryRouter>,
);
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(
<MemoryRouter>

View File

@@ -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({
</span>
</button>
)}
{showEnterpriseSso && (
<button
type="button"
onClick={handleEnterpriseSsoAuth}
className={`${buttonBaseClasses} bg-[#374151] text-white`}
>
<FaUserShield size={14} className="shrink-0" />
<span className={buttonLabelClasses}>
{t(I18nKey.ENTERPRISE_SSO$CONNECT_TO_ENTERPRISE_SSO)}
</span>
</button>
)}
</>
)}
</div>