feat: fix CAS login bug (#2230)

* fix: cas login

* fix: cas login

* feat: rollback get-default-app change

* fix : move cas restrict logic to GetApplicationLogin()

* fix: format code

* fix: fix getOAuthGetParameters for cas

* fix: fix getOAuthGetParameters for cas

* fix: cas login
This commit is contained in:
haiwu 2023-08-19 01:05:55 +08:00 committed by Yang Luo
parent a2db61cc1a
commit fec54944dd
5 changed files with 67 additions and 13 deletions

View File

@ -187,12 +187,35 @@ func (c *ApiController) GetApplicationLogin() {
redirectUri := c.Input().Get("redirectUri")
scope := c.Input().Get("scope")
state := c.Input().Get("state")
id := c.Input().Get("id")
loginType := c.Input().Get("type")
msg, application, err := object.CheckOAuthLogin(clientId, responseType, redirectUri, scope, state, c.GetAcceptLanguage())
var application *object.Application
var msg string
var err error
if loginType == "code" {
msg, application, err = object.CheckOAuthLogin(clientId, responseType, redirectUri, scope, state, c.GetAcceptLanguage())
if err != nil {
c.ResponseError(err.Error())
return
}
} else if loginType == "cas" {
application, err = object.GetApplication(id)
if err != nil {
c.ResponseError(err.Error())
return
}
if application == nil {
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), id))
return
}
err = object.CheckCasLogin(application, c.GetAcceptLanguage(), redirectUri)
if err != nil {
c.ResponseError(err.Error())
return
}
}
application = object.GetMaskedApplication(application, "")
if msg != "" {

View File

@ -26,6 +26,7 @@ import (
"time"
"github.com/beevik/etree"
"github.com/casdoor/casdoor/i18n"
"github.com/casdoor/casdoor/util"
dsig "github.com/russellhaering/goxmldsig"
)
@ -122,6 +123,13 @@ var stToServiceResponse sync.Map
// pgt is short for proxy granting ticket
var pgtToServiceResponse sync.Map
func CheckCasLogin(application *Application, lang string, service string) error {
if len(application.RedirectUris) > 0 && !application.IsRedirectUriValid(service) {
return fmt.Errorf(i18n.Translate(lang, "token:Redirect URI: %s doesn't exist in the allowed Redirect URI list"), service)
}
return nil
}
func StoreCasTokenForPgt(token *CasAuthenticationSuccess, service, userId string) string {
pgt := fmt.Sprintf("PGT-%s", util.GenerateId())
pgtToServiceResponse.Store(pgt, &CasAuthenticationSuccessWrapper{

View File

@ -46,6 +46,10 @@ export function getEmailAndPhone(organization, username) {
}).then((res) => res.json());
}
export function casLoginParamsToQuery(casParams) {
return `?type=${casParams?.type}&id=${casParams?.id}&redirectUri=${casParams?.service}`;
}
export function oAuthParamsToQuery(oAuthParams) {
// login
if (oAuthParams === null || oAuthParams === undefined) {
@ -53,11 +57,12 @@ export function oAuthParamsToQuery(oAuthParams) {
}
// code
return `?clientId=${oAuthParams.clientId}&responseType=${oAuthParams.responseType}&redirectUri=${encodeURIComponent(oAuthParams.redirectUri)}&scope=${oAuthParams.scope}&state=${oAuthParams.state}&nonce=${oAuthParams.nonce}&code_challenge_method=${oAuthParams.challengeMethod}&code_challenge=${oAuthParams.codeChallenge}`;
return `?clientId=${oAuthParams.clientId}&responseType=${oAuthParams.responseType}&redirectUri=${encodeURIComponent(oAuthParams.redirectUri)}&type=${oAuthParams.type}&scope=${oAuthParams.scope}&state=${oAuthParams.state}&nonce=${oAuthParams.nonce}&code_challenge_method=${oAuthParams.challengeMethod}&code_challenge=${oAuthParams.codeChallenge}`;
}
export function getApplicationLogin(oAuthParams) {
return fetch(`${authConfig.serverUrl}/api/get-app-login${oAuthParamsToQuery(oAuthParams)}`, {
export function getApplicationLogin(params) {
const queryParams = (params?.type === "cas") ? casLoginParamsToQuery(params) : oAuthParamsToQuery(params);
return fetch(`${authConfig.serverUrl}/api/get-app-login${queryParams}`, {
method: "GET",
credentials: "include",
headers: {

View File

@ -71,9 +71,9 @@ class LoginPage extends React.Component {
componentDidMount() {
if (this.getApplicationObj() === undefined) {
if (this.state.type === "login" || this.state.type === "cas" || this.state.type === "saml") {
if (this.state.type === "login" || this.state.type === "saml") {
this.getApplication();
} else if (this.state.type === "code") {
} else if (this.state.type === "code" || this.state.type === "cas") {
this.getApplicationLogin();
} else {
Setting.showMessage("error", `Unknown authentication type: ${this.state.type}`);
@ -143,8 +143,8 @@ class LoginPage extends React.Component {
}
getApplicationLogin() {
const oAuthParams = Util.getOAuthGetParameters();
AuthBackend.getApplicationLogin(oAuthParams)
const loginParams = (this.state.type === "cas") ? Util.getCasLoginParameters("admin", this.state.applicationName) : Util.getOAuthGetParameters();
AuthBackend.getApplicationLogin(loginParams)
.then((res) => {
if (res.status === "ok") {
const application = res.data;
@ -167,8 +167,11 @@ class LoginPage extends React.Component {
ApplicationBackend.getApplication("admin", this.state.applicationName)
.then((res) => {
if (res.status === "error") {
Setting.showMessage("error", res.msg);
return;
this.onUpdateApplication(null);
this.setState({
msg: res.msg,
});
return ;
}
this.onUpdateApplication(res.data);
});

View File

@ -96,6 +96,20 @@ function getRawGetParameter(key) {
return res;
}
export function getCasLoginParameters(owner, name) {
const queries = new URLSearchParams(window.location.search);
// CAS service
let service = getRawGetParameter("service");
if (service === "") {
service = getRefinedValue(queries.get("service"));
}
return {
id: `${owner}/${encodeURIComponent(name)}`, // application ID,
service: service,
type: "cas",
};
}
export function getOAuthGetParameters(params) {
const queries = (params !== undefined) ? params : new URLSearchParams(window.location.search);
const clientId = getRefinedValue(queries.get("client_id"));
@ -144,6 +158,7 @@ export function getOAuthGetParameters(params) {
samlRequest: samlRequest,
relayState: relayState,
noRedirect: noRedirect,
type: "code",
};
}
}