diff --git a/object/oidc_discovery.go b/object/oidc_discovery.go index 83330c36..c3f847f5 100644 --- a/object/oidc_discovery.go +++ b/object/oidc_discovery.go @@ -124,7 +124,7 @@ func GetOidcDiscovery(host string) OidcDiscovery { JwksUri: fmt.Sprintf("%s/.well-known/jwks", originBackend), IntrospectionEndpoint: fmt.Sprintf("%s/api/login/oauth/introspect", originBackend), ResponseTypesSupported: []string{"code", "token", "id_token", "code token", "code id_token", "token id_token", "code token id_token", "none"}, - ResponseModesSupported: []string{"query", "fragment"}, + ResponseModesSupported: []string{"query", "fragment", "form_post"}, GrantTypesSupported: []string{"password", "authorization_code"}, SubjectTypesSupported: []string{"public"}, IdTokenSigningAlgValuesSupported: []string{"RS256", "RS512", "ES256", "ES384", "ES512"}, diff --git a/web/src/auth/AuthCallback.js b/web/src/auth/AuthCallback.js index 9eab842e..36042914 100644 --- a/web/src/auth/AuthCallback.js +++ b/web/src/auth/AuthCallback.js @@ -35,6 +35,30 @@ class AuthCallback extends React.Component { }; } + submitFormPost(redirectUri, code, state) { + const form = document.createElement("form"); + form.method = "post"; + form.action = redirectUri; + + const codeInput = document.createElement("input"); + codeInput.type = "hidden"; + codeInput.name = "code"; + codeInput.value = code; + form.appendChild(codeInput); + + if (state) { + const stateInput = document.createElement("input"); + stateInput.type = "hidden"; + stateInput.name = "state"; + stateInput.value = state; + form.appendChild(stateInput); + } + + document.body.appendChild(form); + form.submit(); + setTimeout(() => form.remove(), 1000); + } + getInnerParams() { // For example, for Casbin-OA, realRedirectUri = "http://localhost:9000/login" // realRedirectUrl = "http://localhost:9000" @@ -158,6 +182,7 @@ class AuthCallback extends React.Component { // OAuth const oAuthParams = Util.getOAuthGetParameters(innerParams); const concatChar = oAuthParams?.redirectUri?.includes("?") ? "&" : "?"; + const responseMode = oAuthParams?.responseMode || "query"; // Default to "query" if not specified const signinUrl = localStorage.getItem("signinUrl"); AuthBackend.login(body, oAuthParams) @@ -181,8 +206,13 @@ class AuthCallback extends React.Component { Setting.goToLinkSoft(this, `/forget/${applicationName}`); return; } - const code = res.data; - Setting.goToLink(`${oAuthParams.redirectUri}${concatChar}code=${code}&state=${oAuthParams.state}`); + + if (responseMode === "form_post") { + this.submitFormPost(oAuthParams?.redirectUri, res.data, oAuthParams?.state); + } else { + const code = res.data; + Setting.goToLink(`${oAuthParams.redirectUri}${concatChar}code=${code}&state=${oAuthParams.state}`); + } // Setting.showMessage("success", `Authorization code: ${res.data}`); } else if (responseType === "token" || responseType === "id_token") { if (res.data3) { diff --git a/web/src/auth/Util.js b/web/src/auth/Util.js index 2b06ec69..668a258a 100644 --- a/web/src/auth/Util.js +++ b/web/src/auth/Util.js @@ -141,6 +141,7 @@ export function getOAuthGetParameters(params) { const nonce = getRefinedValue(queries.get("nonce")); const challengeMethod = getRefinedValue(queries.get("code_challenge_method")); const codeChallenge = getRefinedValue(queries.get("code_challenge")); + const responseMode = getRefinedValue(queries.get("response_mode")); const samlRequest = getRefinedValue(lowercaseQueries["samlRequest".toLowerCase()]); const relayState = getRefinedValue(lowercaseQueries["RelayState".toLowerCase()]); const noRedirect = getRefinedValue(lowercaseQueries["noRedirect".toLowerCase()]); @@ -159,6 +160,7 @@ export function getOAuthGetParameters(params) { nonce: nonce, challengeMethod: challengeMethod, codeChallenge: codeChallenge, + responseMode: responseMode, samlRequest: samlRequest, relayState: relayState, noRedirect: noRedirect,