Path: blob/main/components/dashboard/src/dedicated-setup/SSOSetupStep.tsx
2506 views
/**1* Copyright (c) 2023 Gitpod GmbH. All rights reserved.2* Licensed under the GNU Affero General Public License (AGPL).3* See License.AGPL.txt in the project root for license information.4*/56import { FC, useCallback, useReducer, useState } from "react";7import { Heading1, Subheading } from "../components/typography/headings";8import { SetupLayout } from "./SetupLayout";9import { SSOConfigForm, isValid, ssoConfigReducer, useSaveSSOConfig } from "../teams/sso/SSOConfigForm";10import Alert from "../components/Alert";11import { OIDCClientConfig } from "@gitpod/public-api/lib/gitpod/experimental/v1/oidc_pb";12import { openOIDCStartWindow } from "../provider-utils";13import { LoadingButton } from "@podkit/buttons/LoadingButton";1415type Props = {16config?: OIDCClientConfig;17onComplete: () => void;18progressCurrent?: number;19progressTotal?: number;20};21export const SSOSetupStep: FC<Props> = ({ config, onComplete, progressCurrent, progressTotal }) => {22const [ssoLoginError, setSSOLoginError] = useState("");2324const [ssoConfig, dispatch] = useReducer(ssoConfigReducer, {25id: config?.id ?? "",26issuer: config?.oidcConfig?.issuer ?? "",27clientId: config?.oauth2Config?.clientId ?? "",28clientSecret: config?.oauth2Config?.clientSecret ?? "",29celExpression: config?.oauth2Config?.celExpression ?? "",30usePKCE: config?.oauth2Config?.usePkce ?? false,31});32const configIsValid = isValid(ssoConfig);3334const { save, isLoading, isError, error } = useSaveSSOConfig();3536const handleVerify = useCallback(37async (e) => {38e.preventDefault();3940if (isLoading) {41return;42}4344try {45let configId = ssoConfig.id;4647const response = await save(ssoConfig);4849// Create returns the new config, update does not50if ("config" in response && response.config) {51configId = response.config.id;5253// Update our local state with the new config ID in case we created a new one54// This ensures we update the correct config if we save again vs. create a new one55dispatch({56id: configId,57});58}5960await openOIDCStartWindow({61activate: true,62configId: configId,63onSuccess: async () => {64onComplete();65},66onError: (payload) => {67let errorMessage: string;68if (typeof payload === "string") {69errorMessage = payload;70} else {71errorMessage = payload.description ? payload.description : `Error: ${payload.error}`;72}73setSSOLoginError(errorMessage);74},75});76} catch (e) {77console.error(e);78}79},80[isLoading, onComplete, save, ssoConfig],81);8283return (84<SetupLayout showOrg progressCurrent={progressCurrent} progressTotal={progressTotal}>85<div className="mb-10">86<Heading1>Configure single sign-on</Heading1>87<Subheading>88Enable single sign-on for your organization using the OpenID Connect (OIDC) standard.{" "}89<a90href="https://www.gitpod.io/docs/enterprise/setup-gitpod/configure-sso"91target="_blank"92rel="noreferrer noopener"93className="gp-link"94>95Learn more96</a>97</Subheading>98</div>99{isError && <Alert type="danger">{error?.message}</Alert>}100101{ssoLoginError && <Alert type="danger">{ssoLoginError}</Alert>}102103<form onSubmit={handleVerify}>104<SSOConfigForm config={ssoConfig} onChange={dispatch} />105106<div className="mt-6">107<LoadingButton type="submit" className="w-full" disabled={!configIsValid} loading={isLoading}>108Verify SSO Configuration109</LoadingButton>110</div>111</form>112</SetupLayout>113);114};115116117