mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
refactor(console): align sign-in/out redirect uris (#4385)
This commit is contained in:
parent
7b569a4de9
commit
53486f27ad
6 changed files with 37 additions and 26 deletions
|
@ -1,8 +1,7 @@
|
|||
import { useLogto } from '@logto/react';
|
||||
import { useContext, useEffect } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { getCallbackUrl } from '@/consts';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import useRedirectUri from '@/hooks/use-redirect-uri';
|
||||
import { saveRedirect } from '@/utils/storage';
|
||||
|
||||
import AppLoading from '../AppLoading';
|
||||
|
@ -10,14 +9,14 @@ import AppLoading from '../AppLoading';
|
|||
/** This component shows a loading indicator and tries to sign in again. */
|
||||
function SessionExpired() {
|
||||
const { signIn, isLoading } = useLogto();
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const redirectUri = useRedirectUri();
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoading) {
|
||||
saveRedirect();
|
||||
void signIn(getCallbackUrl(currentTenantId).href);
|
||||
void signIn(redirectUri.href);
|
||||
}
|
||||
}, [signIn, isLoading, currentTenantId]);
|
||||
}, [signIn, isLoading, redirectUri]);
|
||||
|
||||
return <AppLoading />;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
import { ossConsolePath } from '@logto/schemas';
|
||||
import { conditionalArray } from '@silverhand/essentials';
|
||||
|
||||
import { adminEndpoint, isCloud } from './env';
|
||||
|
||||
const getAdminTenantEndpoint = () => {
|
||||
|
@ -17,12 +14,3 @@ const getAdminTenantEndpoint = () => {
|
|||
export const adminTenantEndpoint = getAdminTenantEndpoint();
|
||||
|
||||
export const mainTitle = isCloud ? 'Logto Cloud' : 'Logto Console';
|
||||
|
||||
export const getCallbackUrl = (tenantId?: string) =>
|
||||
new URL(
|
||||
// Only Cloud has tenantId in callback URL
|
||||
'/' + conditionalArray(isCloud ? tenantId : 'console', 'callback').join('/'),
|
||||
window.location.origin
|
||||
);
|
||||
|
||||
export const getSignOutRedirectPathname = () => (isCloud ? '/' : ossConsolePath);
|
||||
|
|
|
@ -11,12 +11,12 @@ import Profile from '@/assets/icons/profile.svg';
|
|||
import SignOut from '@/assets/icons/sign-out.svg';
|
||||
import UserAvatar from '@/components/UserAvatar';
|
||||
import UserInfoCard from '@/components/UserInfoCard';
|
||||
import { getSignOutRedirectPathname } from '@/consts';
|
||||
import Divider from '@/ds-components/Divider';
|
||||
import Dropdown, { DropdownItem } from '@/ds-components/Dropdown';
|
||||
import Spacer from '@/ds-components/Spacer';
|
||||
import { Ring as Spinner } from '@/ds-components/Spinner';
|
||||
import useCurrentUser from '@/hooks/use-current-user';
|
||||
import useRedirectUri from '@/hooks/use-redirect-uri';
|
||||
import useTenantPathname from '@/hooks/use-tenant-pathname';
|
||||
import useUserPreferences from '@/hooks/use-user-preferences';
|
||||
import { DynamicAppearanceMode } from '@/types/appearance-mode';
|
||||
|
@ -33,6 +33,7 @@ function UserInfo() {
|
|||
const { user, isLoading: isLoadingUser } = useCurrentUser();
|
||||
const anchorRef = useRef<HTMLDivElement>(null);
|
||||
const [showDropdown, setShowDropdown] = useState(false);
|
||||
const postSignOutRedirectUri = useRedirectUri('signOut');
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const {
|
||||
|
@ -128,7 +129,7 @@ function UserInfo() {
|
|||
return;
|
||||
}
|
||||
setIsLoading(true);
|
||||
void signOut(new URL(getSignOutRedirectPathname(), window.location.origin).toString());
|
||||
void signOut(postSignOutRedirectUri.href);
|
||||
}}
|
||||
>
|
||||
{t('menu.sign_out')}
|
||||
|
|
|
@ -5,8 +5,9 @@ import { Outlet, useSearchParams } from 'react-router-dom';
|
|||
|
||||
import { useCloudApi } from '@/cloud/hooks/use-cloud-api';
|
||||
import AppLoading from '@/components/AppLoading';
|
||||
import { searchKeys, getCallbackUrl } from '@/consts';
|
||||
import { searchKeys } from '@/consts';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import useRedirectUri from '@/hooks/use-redirect-uri';
|
||||
import { saveRedirect } from '@/utils/storage';
|
||||
|
||||
/**
|
||||
|
@ -32,15 +33,16 @@ export default function ProtectedRoutes() {
|
|||
const api = useCloudApi();
|
||||
const [searchParameters] = useSearchParams();
|
||||
const { isAuthenticated, isLoading, signIn } = useLogto();
|
||||
const { currentTenantId, isInitComplete, resetTenants } = useContext(TenantsContext);
|
||||
const { isInitComplete, resetTenants } = useContext(TenantsContext);
|
||||
const redirectUri = useRedirectUri();
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoading && !isAuthenticated) {
|
||||
saveRedirect();
|
||||
const isSignUpMode = yes(searchParameters.get(searchKeys.signUp));
|
||||
void signIn(getCallbackUrl(currentTenantId).href, conditional(isSignUpMode && 'signUp'));
|
||||
void signIn(redirectUri.href, conditional(isSignUpMode && 'signUp'));
|
||||
}
|
||||
}, [currentTenantId, isAuthenticated, isLoading, searchParameters, signIn]);
|
||||
}, [redirectUri, isAuthenticated, isLoading, searchParameters, signIn]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isAuthenticated && !isInitComplete) {
|
||||
|
|
20
packages/console/src/hooks/use-redirect-uri.ts
Normal file
20
packages/console/src/hooks/use-redirect-uri.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { ossConsolePath } from '@logto/schemas';
|
||||
import { conditionalArray } from '@silverhand/essentials';
|
||||
import { useHref } from 'react-router-dom';
|
||||
|
||||
import { isCloud } from '@/consts/env';
|
||||
|
||||
/**
|
||||
* The hook that returns the absolute URL for the sign-in or sign-out callback.
|
||||
* The path is not related to react-router, which means the path will also include
|
||||
* the basename of react-router if it's set.
|
||||
*/
|
||||
const useRedirectUri = (flow: 'signIn' | 'signOut' = 'signIn') => {
|
||||
const path = useHref(
|
||||
conditionalArray(!isCloud && ossConsolePath, flow === 'signIn' && '/callback').join('')
|
||||
);
|
||||
|
||||
return new URL(path, window.location.origin);
|
||||
};
|
||||
|
||||
export default useRedirectUri;
|
|
@ -4,8 +4,8 @@ import { useEffect } from 'react';
|
|||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import Logo from '@/assets/images/logo.svg';
|
||||
import { getCallbackUrl } from '@/consts';
|
||||
import Button from '@/ds-components/Button';
|
||||
import useRedirectUri from '@/hooks/use-redirect-uri';
|
||||
import useTenantPathname from '@/hooks/use-tenant-pathname';
|
||||
import useTheme from '@/hooks/use-theme';
|
||||
|
||||
|
@ -16,6 +16,7 @@ function Welcome() {
|
|||
const { navigate } = useTenantPathname();
|
||||
const { isAuthenticated, signIn } = useLogto();
|
||||
const theme = useTheme();
|
||||
const redirectUri = useRedirectUri();
|
||||
|
||||
useEffect(() => {
|
||||
// If authenticated, navigate to the console root page directly
|
||||
|
@ -40,7 +41,7 @@ function Welcome() {
|
|||
type="branding"
|
||||
title="welcome.create_account"
|
||||
onClick={() => {
|
||||
void signIn(getCallbackUrl().href);
|
||||
void signIn(redirectUri.href);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue