diff --git a/src/contexts/workspaces-context/api.ts b/src/contexts/workspaces-context/api.ts index a72cc138..ccfc90a5 100644 --- a/src/contexts/workspaces-context/api.ts +++ b/src/contexts/workspaces-context/api.ts @@ -292,6 +292,14 @@ export class WorkspacesAPI implements IWorkspacesAPI { window.location.href = url } + @APIRequest() + loginKeycloak() { + // const url = `http://localhost:8080/Keycloak/auth?client_id=django-app&response_type=code&scope=openid&redirect_uri=http://localhost:8000/accounts/keycloak/login/callback/` + + const url = `${this.apiUrl}../../accounts/oidc/keycloak/login/`; + + window.location.href = url + } @APIRequest() loginSAMLGoogle() { /** I've been informed that we aren't actually using Google SAML, we're using OAuth... but this gets the job done regardless. */ diff --git a/src/contexts/workspaces-context/api.types.ts b/src/contexts/workspaces-context/api.types.ts index 19977e0c..876610d0 100644 --- a/src/contexts/workspaces-context/api.types.ts +++ b/src/contexts/workspaces-context/api.types.ts @@ -225,6 +225,7 @@ export interface IWorkspacesAPI { loginSAMLGoogle(): Promise loginSAMLCILogon(): void loginDex(): void + loginKeycloak(): void logout(fetchOptions?: AxiosRequestConfig): Promise /** May throw a WhitelistRequiredError */ diff --git a/src/views/workspaces/login/login.js b/src/views/workspaces/login/login.js index ea18f77b..0989d765 100644 --- a/src/views/workspaces/login/login.js +++ b/src/views/workspaces/login/login.js @@ -6,7 +6,7 @@ import { LoginForm } from '@ant-design/pro-form' import classNames from 'classnames' import { FormWrapper } from './form-wrapper' import { UsernameInput, PasswordInput } from './form-fields' -import { CILogonSSO, GithubSSO, GoogleSSO, UNCSSO, DexOAuth } from './sso' +import { CILogonSSO, GithubSSO, GoogleSSO, UNCSSO, DexOAuth, KeycloakOAuth } from './sso' import { withAPIReady } from '../' import { useDest, useEnvironment, useWorkspacesAPI } from '../../../contexts' import '@ant-design/pro-form/dist/form.css' @@ -40,7 +40,7 @@ const WhitelistRequired = (props) => ( // ) -const SSOLoginOptions = ({ main, unc, google, github, cilogon, dex, onWhitelistRequired, onSignupRequired }) => ( +const SSOLoginOptions = ({ main, unc, google, github, cilogon, dex, keycloak, onWhitelistRequired, onSignupRequired }) => (
@@ -63,6 +63,9 @@ const SSOLoginOptions = ({ main, unc, google, github, cilogon, dex, onWhitelistR { dex && ( ) } + { keycloak && ( + + ) }
) @@ -97,14 +100,16 @@ export const WorkspaceLoginView = withAPIReady(({ const allowGithubLogin = useMemo(() => loginProviders.includes("GitHub"), [loginProviders]) const allowCILogon = useMemo(() => loginProviders.includes("CILogon"), [loginProviders]) const allowDexLogon = useMemo(() => loginProviders.includes("dex"), [loginProviders]) + const allowKeycloakLogon = useMemo(() => loginProviders.includes("keycloak"), [loginProviders]) const hasAdditionalProviders = useMemo(() => ( allowUncLogin || allowGoogleLogin || allowGithubLogin || allowCILogon || - allowDexLogon - ), [allowUncLogin, allowGoogleLogin, allowGithubLogin, allowCILogon, allowDexLogon]) + allowDexLogon || + allowKeycloakLogon + ), [allowUncLogin, allowGoogleLogin, allowGithubLogin, allowCILogon, allowDexLogon, allowKeycloakLogon]) const showWhitelistRequired = useMemo(() => { const required = new URLSearchParams(location.search).get("whitelist_required") @@ -219,6 +224,7 @@ export const WorkspaceLoginView = withAPIReady(({ github={ allowGithubLogin } cilogon={ allowCILogon } dex={ allowDexLogon } + keycloak={ allowKeycloakLogon } onWhitelistRequired={ () => { setShowWhitelistRequired(true) } } diff --git a/src/views/workspaces/login/sso/index.js b/src/views/workspaces/login/sso/index.js index d273a82c..1ba0fa5a 100644 --- a/src/views/workspaces/login/sso/index.js +++ b/src/views/workspaces/login/sso/index.js @@ -2,4 +2,5 @@ export * from './unc-sso' export * from './cilogon-sso' export * from './dex-oauth' export * from './google-sso' -export * from './github-sso' \ No newline at end of file +export * from './github-sso' +export * from './keycloak-oauth' \ No newline at end of file diff --git a/src/views/workspaces/login/sso/keycloak-glyph-color.png b/src/views/workspaces/login/sso/keycloak-glyph-color.png new file mode 100644 index 00000000..90ab618d Binary files /dev/null and b/src/views/workspaces/login/sso/keycloak-glyph-color.png differ diff --git a/src/views/workspaces/login/sso/keycloak-oauth.js b/src/views/workspaces/login/sso/keycloak-oauth.js new file mode 100644 index 00000000..6a50a17d --- /dev/null +++ b/src/views/workspaces/login/sso/keycloak-oauth.js @@ -0,0 +1,38 @@ +import { useMemo } from 'react' +import { useWorkspacesAPI } from '../../../../contexts' +import { SAMLButton } from './sso-button' +import KeycloakPng from './keycloak-glyph-color.png' +import Icon from '@ant-design/icons' + + +/* + Component to render the button and handling of the Dex OAuth + */ +export const KeycloakOAuth = (props) => { + // get the context for the workspaces + const { api } = useWorkspacesAPI() + + // create some state for the icon + const icon = useMemo(() => ( + ( + + ) } /> + ), []) + + // return the button control for rendering + return ( + api.loginKeycloak() } + { ...props } + > + + ) +} \ No newline at end of file