diff --git a/client/packages/lowcoder/src/appView/AppViewInstance.tsx b/client/packages/lowcoder/src/appView/AppViewInstance.tsx index 4bcc9953b..2bbbfbc05 100644 --- a/client/packages/lowcoder/src/appView/AppViewInstance.tsx +++ b/client/packages/lowcoder/src/appView/AppViewInstance.tsx @@ -11,6 +11,7 @@ import { AppView } from "./AppView"; import { API_STATUS_CODES } from "constants/apiConstants"; import { AUTH_LOGIN_URL } from "constants/routesURL"; import { AuthSearchParams } from "constants/authConstants"; +import { saveAuthSearchParams } from "@lowcoder-ee/pages/userAuth/authUtils"; export type OutputChangeHandler = (output: O) => void; export type EventTriggerHandler = (eventName: string) => void; @@ -71,9 +72,11 @@ export class AppViewInstance { .then((i) => i.data) .catch((e) => { if (e.response?.status === API_STATUS_CODES.REQUEST_NOT_AUTHORISED) { - window.location.href = `${webUrl}${AUTH_LOGIN_URL}?${ - AuthSearchParams.redirectUrl - }=${encodeURIComponent(window.location.href)}`; + saveAuthSearchParams({ + [AuthSearchParams.redirectUrl]: encodeURIComponent(window.location.href), + [AuthSearchParams.loginType]: null, + }) + window.location.href = `${webUrl}${AUTH_LOGIN_URL}`; } }); diff --git a/client/packages/lowcoder/src/constants/authConstants.ts b/client/packages/lowcoder/src/constants/authConstants.ts index bd92adaa2..0207d6abf 100644 --- a/client/packages/lowcoder/src/constants/authConstants.ts +++ b/client/packages/lowcoder/src/constants/authConstants.ts @@ -22,9 +22,14 @@ import { export type AuthInviteInfo = InviteInfo & { invitationId: string }; export type AuthLocationState = { inviteInfo?: AuthInviteInfo; thirdPartyAuthError?: boolean }; -export const AuthSearchParams = { - loginType: "loginType", - redirectUrl: "redirectUrl", +export enum AuthSearchParams { + loginType = "loginType", + redirectUrl = "redirectUrl", +}; + +export type AuthSearchParamsType = { + loginType: string | null, + redirectUrl: string | null, }; export type OauthRequestParam = { diff --git a/client/packages/lowcoder/src/constants/routesURL.ts b/client/packages/lowcoder/src/constants/routesURL.ts index be07a63a7..8b7abb5ee 100644 --- a/client/packages/lowcoder/src/constants/routesURL.ts +++ b/client/packages/lowcoder/src/constants/routesURL.ts @@ -39,7 +39,6 @@ export const QR_CODE_OAUTH_URL = `${USER_AUTH_URL}/oauth/qrcode`; export const OAUTH_REDIRECT = `${USER_AUTH_URL}/oauth/redirect`; export const CAS_AUTH_REDIRECT = `${USER_AUTH_URL}/cas/redirect`; export const LDAP_AUTH_LOGIN_URL = `${USER_AUTH_URL}/ldap/login`; -export const USER_INFO_COMPLETION = `${USER_AUTH_URL}/completion`; export const INVITE_LANDING_URL = "/invite/:invitationId"; export const ORG_AUTH_LOGIN_URL = `/org/:orgId/auth/login`; export const ORG_AUTH_REGISTER_URL = `/org/:orgId/auth/register`; diff --git a/client/packages/lowcoder/src/pages/userAuth/authUtils.ts b/client/packages/lowcoder/src/pages/userAuth/authUtils.ts index 36363b778..ccc0ac880 100644 --- a/client/packages/lowcoder/src/pages/userAuth/authUtils.ts +++ b/client/packages/lowcoder/src/pages/userAuth/authUtils.ts @@ -3,7 +3,6 @@ import { BASE_URL, CAS_AUTH_REDIRECT, OAUTH_REDIRECT, - USER_INFO_COMPLETION, } from "constants/routesURL"; import { AxiosPromise, AxiosResponse } from "axios"; import { ApiResponse } from "api/apiResponses"; @@ -16,6 +15,7 @@ import { createContext, useState } from "react"; import { SystemConfig } from "constants/configConstants"; import { AuthInviteInfo, + AuthSearchParamsType, AuthSessionStoreParams, ThirdPartyAuthGoal, ThirdPartyAuthType, @@ -79,12 +79,7 @@ export function authRespValidate( ) { let replaceUrl = redirectUrl || BASE_URL; const baseUrl = `${window.location.protocol}//${window.location.host}`; - if (infoCompleteCheck) { - // need complete info - replaceUrl = redirectUrl - ? `${USER_INFO_COMPLETION}?redirectUrl=${redirectUrl}` - : USER_INFO_COMPLETION; - } + if (doValidResponse(resp)) { onAuthSuccess?.(); history.replace(replaceUrl.replace(baseUrl, '')); @@ -185,3 +180,21 @@ export const getRedirectUrl = (authType: ThirdPartyAuthType) => { `${window.location.origin}${authType === "CAS" ? CAS_AUTH_REDIRECT : OAUTH_REDIRECT}` ); }; + +const AuthSearchParamStorageKey = "_temp_auth_search_params_"; + +export const saveAuthSearchParams = ( + authSearchParams: AuthSearchParamsType +) => { + sessionStorage.setItem(AuthSearchParamStorageKey, JSON.stringify(authSearchParams)); +} + +export const loadAuthSearchParams = ():AuthSearchParamsType | null => { + const authParams = sessionStorage.getItem(AuthSearchParamStorageKey); + if (!authParams) return null; + return JSON.parse(authParams); +} + +export const clearAuthSearchParams = () => { + sessionStorage.removeItem(AuthSearchParamStorageKey); +} diff --git a/client/packages/lowcoder/src/pages/userAuth/index.tsx b/client/packages/lowcoder/src/pages/userAuth/index.tsx index 78f5a95d6..7d28cd551 100644 --- a/client/packages/lowcoder/src/pages/userAuth/index.tsx +++ b/client/packages/lowcoder/src/pages/userAuth/index.tsx @@ -3,7 +3,7 @@ import { Redirect, Route, Switch, useLocation, useParams } from "react-router-do import React, { useEffect, useMemo } from "react"; import { useSelector, useDispatch } from "react-redux"; import { selectSystemConfig } from "redux/selectors/configSelectors"; -import { AuthContext } from "pages/userAuth/authUtils"; +import { AuthContext, clearAuthSearchParams } from "pages/userAuth/authUtils"; import { AuthRoutes } from "@lowcoder-ee/constants/authConstants"; import { AuthLocationState } from "constants/authConstants"; import { ProductLoading } from "components/ProductLoading"; @@ -37,6 +37,7 @@ export default function UserAuth() { const fetchUserAfterAuthSuccess = () => { dispatch(fetchUserAction()); + clearAuthSearchParams(); } return ( diff --git a/client/packages/lowcoder/src/pages/userAuth/thirdParty/authenticator/abstractAuthenticator.ts b/client/packages/lowcoder/src/pages/userAuth/thirdParty/authenticator/abstractAuthenticator.ts index 99682e777..81da2a54b 100644 --- a/client/packages/lowcoder/src/pages/userAuth/thirdParty/authenticator/abstractAuthenticator.ts +++ b/client/packages/lowcoder/src/pages/userAuth/thirdParty/authenticator/abstractAuthenticator.ts @@ -39,7 +39,7 @@ export abstract class AbstractAuthenticator { authRespValidate( resp, this.needInfoCheck(this.authParams.sourceType), - this.authParams.afterLoginRedirect, + getSafeAuthRedirectURL(this.authParams.afterLoginRedirect), onAuthSuccess, ); }) diff --git a/client/packages/lowcoder/src/pages/userAuth/thirdParty/thirdPartyAuth.tsx b/client/packages/lowcoder/src/pages/userAuth/thirdParty/thirdPartyAuth.tsx index 14d7fc189..78017a639 100644 --- a/client/packages/lowcoder/src/pages/userAuth/thirdParty/thirdPartyAuth.tsx +++ b/client/packages/lowcoder/src/pages/userAuth/thirdParty/thirdPartyAuth.tsx @@ -1,11 +1,9 @@ import { - AuthSearchParams, OAuthLocationState, ThirdPartyAuthGoal, ThirdPartyConfigType, } from "constants/authConstants"; -import { CommonGrayLabel, WhiteLoading } from "lowcoder-design"; -import { useLocation } from "react-router-dom"; +import { WhiteLoading } from "lowcoder-design"; import history from "util/history"; import { LoginLogoStyle, LoginLabelStyle, StyledLoginButton } from "pages/userAuth/authComponents"; import { useSelector } from "react-redux"; @@ -16,6 +14,7 @@ import styled from "styled-components"; import { trans } from "i18n"; import { geneAuthStateAndSaveParam, getAuthUrl, getRedirectUrl } from "pages/userAuth/authUtils"; import { Divider } from "antd"; +import { useRedirectUrl } from "util/hooks"; const ThirdPartyLoginButtonWrapper = styled.div` button{ @@ -36,9 +35,7 @@ function ThirdPartyLoginButton(props: { label: string; }) { const { config, label } = props; - const location = useLocation(); - const queryParams = new URLSearchParams(location.search); - const loginRedirectUrl = queryParams.get(AuthSearchParams.redirectUrl); + const loginRedirectUrl = useRedirectUrl(); const redirectUrl = getRedirectUrl(config.authType); const onLoginClick = () => { const state = geneAuthStateAndSaveParam( diff --git a/client/packages/lowcoder/src/redux/sagas/userSagas.ts b/client/packages/lowcoder/src/redux/sagas/userSagas.ts index f2e441d77..7a78622cd 100644 --- a/client/packages/lowcoder/src/redux/sagas/userSagas.ts +++ b/client/packages/lowcoder/src/redux/sagas/userSagas.ts @@ -23,6 +23,7 @@ import { defaultUser } from "constants/userConstants"; import { messageInstance } from "lowcoder-design"; import { AuthSearchParams } from "constants/authConstants"; +import { saveAuthSearchParams } from "pages/userAuth/authUtils"; function validResponseData(response: AxiosResponse) { return response && response.data && response.data.data; @@ -132,14 +133,14 @@ export function* logoutSaga(action: LogoutActionType) { try { let redirectURL = AUTH_LOGIN_URL; if (action.payload.notAuthorised) { - const currentUrl = window.location.href; - redirectURL = `${AUTH_LOGIN_URL}?redirectUrl=${encodeURIComponent(currentUrl)}`; + const currentUrl = window.location.href const urlObj = new URL(currentUrl); // Add loginType param for auto login jump const loginType = urlObj.searchParams.get(AuthSearchParams.loginType); - if (loginType) { - redirectURL = redirectURL + `&${AuthSearchParams.loginType}=${loginType}`; - } + saveAuthSearchParams({ + [AuthSearchParams.redirectUrl]: encodeURIComponent(currentUrl), + [AuthSearchParams.loginType]: loginType + }); } let isValidResponse = true; if (!action.payload.notAuthorised) { diff --git a/client/packages/lowcoder/src/util/hooks.ts b/client/packages/lowcoder/src/util/hooks.ts index f427d1fc0..67e397184 100644 --- a/client/packages/lowcoder/src/util/hooks.ts +++ b/client/packages/lowcoder/src/util/hooks.ts @@ -16,6 +16,7 @@ import { checkIsMobile } from "util/commonUtils"; import { EditorContext } from "comps/editorState"; import { getDataSourceStructures } from "redux/selectors/datasourceSelectors"; import { DatasourceStructure } from "api/datasourceApi"; +import { loadAuthSearchParams } from "pages/userAuth/authUtils"; export const ForceViewModeContext = React.createContext(false); @@ -59,9 +60,9 @@ export function useApplicationId() { } export function useRedirectUrl() { - const location = useLocation(); - const queryParams = new URLSearchParams(location.search); - return queryParams.get(AuthSearchParams.redirectUrl); + const authSearchParams = loadAuthSearchParams() + const redirectUrl = authSearchParams && authSearchParams.redirectUrl + return redirectUrl && decodeURIComponent(redirectUrl); } export function useFixedDelay(callback: () => Promise, delay: number | null) {