diff --git a/conf/app.conf b/conf/app.conf index ede68384..474d2f5d 100644 --- a/conf/app.conf +++ b/conf/app.conf @@ -15,5 +15,4 @@ verificationCodeTimeout = 10 initScore = 2000 logPostOnly = true oidcOrigin = "https://door.casbin.com" -samlOrigin = "http://localhost:8000" -samlRequestOrigin = "http://localhost:7001" \ No newline at end of file +samlOrigin = "http://localhost:8000" \ No newline at end of file diff --git a/controllers/auth.go b/controllers/auth.go index cae2c614..223fd268 100644 --- a/controllers/auth.go +++ b/controllers/auth.go @@ -15,6 +15,7 @@ package controllers import ( + "encoding/base64" "encoding/json" "fmt" "net/url" @@ -369,8 +370,14 @@ func (c *ApiController) GetSamlLogin() { func (c *ApiController) HandleSamlLogin() { relayState := c.Input().Get("RelayState") samlResponse := c.Input().Get("SAMLResponse") + decode, err := base64.StdEncoding.DecodeString(relayState) + if err != nil { + c.ResponseError(err.Error()) + } + slice := strings.Split(string(decode), "&") + relayState = url.QueryEscape(relayState) samlResponse = url.QueryEscape(samlResponse) - targetUrl := fmt.Sprintf("%s/callback/saml?replayState=%s&samlResponse=%s", - beego.AppConfig.String("samlRequestOrigin"), relayState, samlResponse) + targetUrl := fmt.Sprintf("%s?relayState=%s&samlResponse=%s", + slice[4], relayState, samlResponse) c.Redirect(targetUrl, 303) } diff --git a/web/src/auth/AuthBackend.js b/web/src/auth/AuthBackend.js index 497dbca3..137dd68e 100644 --- a/web/src/auth/AuthBackend.js +++ b/web/src/auth/AuthBackend.js @@ -84,8 +84,8 @@ export function getSamlLogin(providerId) { }).then(res => res.json()); } -export function loginWithSaml(values) { - return fetch(`${authConfig.serverUrl}/api/login`, { +export function loginWithSaml(values, param) { + return fetch(`${authConfig.serverUrl}/api/login${param}`, { method: 'POST', credentials: "include", body: JSON.stringify(values), diff --git a/web/src/auth/LoginPage.js b/web/src/auth/LoginPage.js index 0b910968..d2e207e1 100644 --- a/web/src/auth/LoginPage.js +++ b/web/src/auth/LoginPage.js @@ -186,8 +186,15 @@ class LoginPage extends React.Component { } getSamlUrl(providerId) { + const params = new URLSearchParams(this.props.location.search); + let clientId = params.get("client_id") + let application = params.get("state"); + let realRedirectUri = params.get("redirect_uri"); + let redirectUri = `${window.location.origin}/callback/saml` + let providerName = providerId.split('/')[1]; AuthBackend.getSamlLogin(providerId).then((res) => { - window.location.href = res.data + const replyState = `${clientId}&${application}&${providerName}&${realRedirectUri}&${redirectUri}`; + window.location.href = `${res.data}&RelayState=${btoa(replyState)}`; }); } diff --git a/web/src/auth/SamlCallback.js b/web/src/auth/SamlCallback.js index c5eb21a9..2ef1c646 100644 --- a/web/src/auth/SamlCallback.js +++ b/web/src/auth/SamlCallback.js @@ -19,6 +19,7 @@ import * as AuthBackend from "./AuthBackend"; import * as Util from "./Util"; import * as Setting from "../Setting"; import i18next from "i18next"; +import {authConfig} from "./Auth"; class SamlCallback extends React.Component { constructor(props) { @@ -29,28 +30,61 @@ class SamlCallback extends React.Component { }; } + getResponseType(redirectUri) { + const authServerUrl = authConfig.serverUrl; + // Casdoor's own login page, so "code" is not necessary + if (redirectUri === "null") { + return "login"; + } + const realRedirectUrl = new URL(redirectUri).origin; + // For Casdoor itself, we use "login" directly + if (authServerUrl === realRedirectUrl) { + return "login"; + } else { + return "code"; + } + } + UNSAFE_componentWillMount() { const params = new URLSearchParams(this.props.location.search); let relayState = params.get('relayState') let samlResponse = params.get('samlResponse') - let redirectUri = `${window.location.origin}/callback`; - const applicationName = "app-built-in" + const messages = atob(relayState).split('&'); + const clientId = messages[0]; + const applicationName = messages[1] === "null" ? "app-built-in" : messages[1]; + const providerName = messages[2]; + const redirectUri = messages[3]; + const responseType = this.getResponseType(redirectUri); + const body = { - type: "login", + type: responseType, application: applicationName, - provider: "aliyun-idaas", + provider: providerName, state: applicationName, - redirectUri: redirectUri, + redirectUri: `${window.location.origin}/callback`, method: "signup", relayState: relayState, samlResponse: encodeURIComponent(samlResponse), }; - AuthBackend.loginWithSaml(body) + + let param; + if (clientId === null || clientId === "") { + param = "" + } else { + param = `?clientId=${clientId}&responseType=${responseType}&redirectUri=${redirectUri}&scope=read&state=${applicationName}` + } + + AuthBackend.loginWithSaml(body, param) .then((res) => { if (res.status === 'ok') { - Util.showMessage("success", `Logged in successfully`); - // Setting.goToLinkSoft(this, "/"); - Setting.goToLink("/"); + const responseType = this.getResponseType(redirectUri); + if (responseType === "login") { + Util.showMessage("success", `Logged in successfully`); + Setting.goToLink("/"); + } else if (responseType === "code") { + const code = res.data; + Setting.goToLink(`${redirectUri}?code=${code}&state=${applicationName}`); + } } else { this.setState({ msg: res.msg,