diff --git a/backend/go-app/main.go b/backend/go-app/main.go index 9423eadd..aac348fe 100644 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -857,6 +857,7 @@ func handleInfo(resp http.ResponseWriter, request *http.Request) { userInfo, err := shuffle.HandleApiAuthentication(resp, request) if err != nil { log.Printf("[WARNING] Api authentication failed in handleInfo: %s", err) + resp.WriteHeader(401) resp.Write([]byte(`{"success": false}`)) return @@ -1177,8 +1178,10 @@ func checkAdminLogin(resp http.ResponseWriter, request *http.Request) { return } + //ssoUrl = org.SSOConfig.SOSOEntrypoint + redirectUri := shuffle.SSOUrl resp.WriteHeader(200) - resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "redirect"}`))) + resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "redirect", "sso_url": "%s"}`, redirectUri))) } func handleLogin(resp http.ResponseWriter, request *http.Request) { @@ -5866,7 +5869,7 @@ func initHandlers() { // Docker orborus specific - downloads an image r.HandleFunc("/api/v1/get_docker_image", getDockerImage).Methods("POST", "OPTIONS") r.HandleFunc("/api/v1/migrate_database", migrateDatabase).Methods("POST", "OPTIONS") - r.HandleFunc("/api/v1/login_sso", shuffle.HandleSSO).Methods("GET", "POST", "OPTIONS") + r.HandleFunc("/api/v1/login_sso", shuffle.HandleSSO).Methods("POST", "OPTIONS") // Important for email, IDS etc. Create this by: // PS: For cloud, this has to use cloud storage. diff --git a/frontend/src/components/OrgHeader.js b/frontend/src/components/OrgHeader.js index 5d86745a..896517dc 100644 --- a/frontend/src/components/OrgHeader.js +++ b/frontend/src/components/OrgHeader.js @@ -36,6 +36,8 @@ const OrgHeader = (props) => { const [appDownloadBranch, setAppDownloadBranch] = React.useState(selectedOrganization.defaults === undefined ? defaultBranch : selectedOrganization.defaults.app_download_branch === undefined || selectedOrganization.defaults.app_download_branch.length === 0 ? defaultBranch : selectedOrganization.defaults.app_download_branch) const [workflowDownloadUrl, setWorkflowDownloadUrl] = React.useState(selectedOrganization.defaults === undefined ? "https://github.com/frikky/shuffle-apps" : selectedOrganization.defaults.workflow_download_repo === undefined || selectedOrganization.defaults.workflow_download_repo.length === 0 ? "https://github.com/frikky/shuffle-workflows" : selectedOrganization.defaults.workflow_download_repo) const [workflowDownloadBranch, setWorkflowDownloadBranch] = React.useState(selectedOrganization.defaults === undefined ? defaultBranch : selectedOrganization.defaults.workflow_download_branch === undefined || selectedOrganization.defaults.workflow_download_branch.length === 0 ? defaultBranch : selectedOrganization.defaults.workflow_download_branch) + const [ssoEntrypoint, setSsoEntrypoint] = React.useState(selectedOrganization.sso_config === undefined ? "" : selectedOrganization.sso_config.sso_entrypoint === undefined || selectedOrganization.sso_config.sso_entrypoint.length === 0 ? "" : selectedOrganization.sso_config.sso_entrypoint) + const [ssoCertificate, setSsoCertificate] = React.useState(selectedOrganization.sso_config === undefined ? "" : selectedOrganization.sso_config.sso_certificate === undefined || selectedOrganization.sso_config.sso_certificate.length === 0 ? "" : selectedOrganization.sso_config.sso_certificate) const [file, setFile] = React.useState("") const [fileBase64, setFileBase64] = React.useState(selectedOrganization.image) @@ -67,13 +69,14 @@ const OrgHeader = (props) => { } } - const handleEditOrg = (name, description, orgId, image, defaults) => { + const handleEditOrg = (name, description, orgId, image, defaults, sso_config) => { const data = { "name": name, "description": description, "org_id": orgId, "image": image, "defaults": defaults, + "sso_config": sso_config, } const url = globalUrl + `/api/v1/orgs/${selectedOrganization.id}`; @@ -111,19 +114,25 @@ const OrgHeader = (props) => { } const orgSaveButton = - + + + var imageData = file.length > 0 ? file : fileBase64 imageData = imageData === undefined || imageData.length === 0 ? defaultImage : imageData @@ -337,6 +346,69 @@ const OrgHeader = (props) => { /> + + + + SSO Entrypoint + + 0} + id="outlined-with-placeholder" + margin="normal" + variant="outlined" + placeholder="The entrypoint URL from your provider" + value={ssoEntrypoint} + onChange={e => { + setSsoEntrypoint(e.target.value) + }} + InputProps={{ + classes: { + notchedOutline: classes.notchedOutline, + }, + style:{ + color: "white", + }, + }} + /> + + + + + + SSO Certificate + + { + setSsoCertificate(e.target.value) + }} + InputProps={{ + classes: { + notchedOutline: classes.notchedOutline, + }, + style:{ + color: "white", + }, + }} + /> + + {/* {expanded ? diff --git a/frontend/src/views/LoginPage.jsx b/frontend/src/views/LoginPage.jsx index 1b621751..35ee4e90 100644 --- a/frontend/src/views/LoginPage.jsx +++ b/frontend/src/views/LoginPage.jsx @@ -34,6 +34,7 @@ const LoginDialog = props => { const [firstRequest, setFirstRequest] = useState(true); const [loginLoading, setLoginLoading] = useState(false); const [loginViewLoading, setLoginViewLoading] = useState(false); + const [ssoUrl, setSSOUrl] = useState("") // Used to swap from login to register. True = login, false = register @@ -62,6 +63,10 @@ const LoginDialog = props => { if (responseJson["success"] === false) { setLoginInfo(responseJson["reason"]) } else { + if (responseJson.sso_url !== undefined && responseJson.sso_url !== null) { + setSSOUrl(responseJson.sso_url) + } + if (loginViewLoading) { setLoginViewLoading(false) checkLogin() @@ -306,17 +311,21 @@ const LoginDialog = props => {
{loginInfo}
- - Or - -
- -
+ {ssoUrl !== undefined && ssoUrl !== null && ssoUrl.length > 0 ? +
+ + Or + +
+ +
+
+ : null} }