Hello,
We are experimenting with react ( current front is in ExtJS) and we want to have the login page to be shown as soon as the application start (unless the user is already logged in).
All the documentation on auth0 is about a login button, we have sensitive data so it’s mandatory for a user to be logged in at any time.
How can I achieve this ?
Here’s what I have at the moment :
main.tsx (equivalent of index.js I think)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import React, { Suspense } from 'react';
import { Provider } from 'react-redux';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import { Auth0Provider } from '@auth0/auth0-react';
import App from './App';
import { store } from './store/Store';
import Spinner from './views/spinner/Spinner';
import './utils/i18n';
import './_mockApis';
import AuthHandler from './components/authentication/AuthHandler';
ReactDOM.createRoot(document.getElementById('root')!).render(
<Auth0Provider
domain={import.meta.env.VITE_AUTH0_DOMAIN}
clientId={import.meta.env.VITE_AUTH0_CLIENT_ID}
authorizationParams={{
redirect_uri: window.location.origin,
audience: import.meta.env.VITE_AUTH0_AUDIENCE,
organization: import.meta.env.VITE_AUTH0_ORGANIZATION
}}
>
<AuthHandler />
<Provider store={store}>
<Suspense fallback={<Spinner />}>
<BrowserRouter>
<App />
</BrowserRouter>
</Suspense>
</Provider>
</Auth0Provider>,
)
AuthHandler.tsx:
import { useEffect, FC } from 'react';
import { useAuth0 } from '@auth0/auth0-react';
const AuthHandler: FC = () => {
const { isAuthenticated, isLoading, loginWithRedirect } = useAuth0();
useEffect(() => {
console.log('user is authenticated !')
if (!isLoading && !isAuthenticated) {
loginWithRedirect(); // Redirect to login if not authenticated
}
}, [isAuthenticated, isLoading, loginWithRedirect]);
if (isLoading) {
return null;
}
return null; // Return null or a fallback UI while checking auth state
};
export default AuthHandler;
App.tsx:
import { CssBaseline, ThemeProvider } from "@mui/material";
import { useRoutes } from "react-router-dom";
import { useSelector } from "src/store/Store";
import { ThemeSettings } from "./theme/Theme";
import RTL from "./layouts/full/shared/customizer/RTL";
import ScrollToTop from "./components/shared/ScrollToTop";
import Router from "./routes/Router";
import { AppState } from "./store/Store";
import { PermissionsProvider } from "./contexts/PermissionsContext"; // Import the PermissionsProvider
function App() {
const routing = useRoutes(Router);
const theme = ThemeSettings();
const customizer = useSelector((state: AppState) => state.customizer);
return (
<PermissionsProvider>
<ThemeProvider theme={theme}>
<RTL direction={customizer.activeDir}>
<CssBaseline />
<ScrollToTop>{routing}</ScrollToTop>
</RTL>
</ThemeProvider>
</PermissionsProvider>
);
}
export default App;
And the component that make the API call:
import React, { createContext, useState, useEffect, ReactNode, useContext } from 'react';
import { useAuth0 } from '@auth0/auth0-react'; // Ensure this is the correct path to your Auth0 hook
import PermissionController from '../controllers/PermissionController';
// Define the shape of the structure item and context state
interface StructureItem {
id: number;
category: string;
code: string;
caption: string;
}
interface PermissionsContextState {
items: StructureItem[];
loading: boolean;
error: Error | null;
}
// Create the context with a default empty state
const PermissionsContext = createContext<PermissionsContextState>({
items: [],
loading: true,
error: null,
});
interface PermissionsProviderProps {
children: ReactNode;
}
// Create a provider component
export const PermissionsProvider: React.FC<PermissionsProviderProps> = ({ children }) => {
const [items, setItems] = useState<StructureItem[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
const { isAuthenticated, getAccessTokenSilently } = useAuth0();
useEffect(() => {
// Fetch structure items from the API using the custom service
const fetchItems = async () => {
if (!isAuthenticated) {
console.log('user not authenticated !')
setLoading(false);
return;
}
try {
const accessToken = await getAccessTokenSilently();
console.log(accessToken);
const data: StructureItem[] = await PermissionController.getFlatStructure(accessToken);
setItems(data);
} catch (err) {
setError(err as Error);
} finally {
setLoading(false);
}
};
fetchItems();
}, [isAuthenticated, getAccessTokenSilently]);
return (
<PermissionsContext.Provider value={{ items, loading, error }}>
{children}
</PermissionsContext.Provider>
);
};
// Custom hook to use the PermissionsContext
export const usePermissions = () => {
return useContext(PermissionsContext);
};
the call does not go through because the user is not authenticated, but I authenticated myself when the application started.
What am I doing wrong ?