mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-18 05:10:45 +00:00
Refactor authentication handling to pass authentication metadata into App.
eliminates warnings from oauth2 hook by conditionally using its useAuth hook.
This commit is contained in:
22
src/App.tsx
22
src/App.tsx
@ -63,9 +63,14 @@ import {Md5} from "ts-md5/dist/md5";
|
|||||||
const qController = Client.getInstance();
|
const qController = Client.getInstance();
|
||||||
export const SESSION_UUID_COOKIE_NAME = "sessionUUID";
|
export const SESSION_UUID_COOKIE_NAME = "sessionUUID";
|
||||||
|
|
||||||
export default function App()
|
interface Props
|
||||||
{
|
{
|
||||||
const [cookies, setCookie, removeCookie] = useCookies([SESSION_UUID_COOKIE_NAME]);
|
authenticationMetaData: QAuthenticationMetaData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function App({authenticationMetaData}: Props)
|
||||||
|
{
|
||||||
|
const [, , removeCookie] = useCookies([SESSION_UUID_COOKIE_NAME]);
|
||||||
const [loadingToken, setLoadingToken] = useState(false);
|
const [loadingToken, setLoadingToken] = useState(false);
|
||||||
const [isFullyAuthenticated, setIsFullyAuthenticated] = useState(false);
|
const [isFullyAuthenticated, setIsFullyAuthenticated] = useState(false);
|
||||||
const [profileRoutes, setProfileRoutes] = useState({});
|
const [profileRoutes, setProfileRoutes] = useState({});
|
||||||
@ -74,11 +79,10 @@ export default function App()
|
|||||||
const [needLicenseKey, setNeedLicenseKey] = useState(true);
|
const [needLicenseKey, setNeedLicenseKey] = useState(true);
|
||||||
const [loggedInUser, setLoggedInUser] = useState({} as { name?: string, email?: string });
|
const [loggedInUser, setLoggedInUser] = useState({} as { name?: string, email?: string });
|
||||||
const [defaultRoute, setDefaultRoute] = useState("/no-apps");
|
const [defaultRoute, setDefaultRoute] = useState("/no-apps");
|
||||||
const [authenticationMetaData, setAuthenticationMetaData] = useState(null as QAuthenticationMetaData | null);
|
|
||||||
const [earlyReturnForAuth, setEarlyReturnForAuth] = useState(null as JSX.Element);
|
const [earlyReturnForAuth, setEarlyReturnForAuth] = useState(null as JSX.Element);
|
||||||
|
|
||||||
const {setupSession: auth0SetupSession, logout: auth0Logout} = useAuth0AuthenticationModule({setIsFullyAuthenticated, setLoggedInUser, setEarlyReturnForAuth});
|
const {setupSession: auth0SetupSession, logout: auth0Logout} = useAuth0AuthenticationModule({setIsFullyAuthenticated, setLoggedInUser, setEarlyReturnForAuth});
|
||||||
const {setupSession: oauth2SetupSession, logout: oauth2Logout} = useOAuth2AuthenticationModule({setIsFullyAuthenticated, setLoggedInUser, setEarlyReturnForAuth});
|
const {setupSession: oauth2SetupSession, logout: oauth2Logout} = useOAuth2AuthenticationModule({setIsFullyAuthenticated, setLoggedInUser, setEarlyReturnForAuth, inOAuthContext: authenticationMetaData.type === "OAUTH2"});
|
||||||
const {setupSession: anonymousSetupSession, logout: anonymousLogout} = useAnonymousAuthenticationModule({setIsFullyAuthenticated, setLoggedInUser, setEarlyReturnForAuth});
|
const {setupSession: anonymousSetupSession, logout: anonymousLogout} = useAnonymousAuthenticationModule({setIsFullyAuthenticated, setLoggedInUser, setEarlyReturnForAuth});
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////
|
||||||
@ -99,9 +103,6 @@ export default function App()
|
|||||||
|
|
||||||
(async () =>
|
(async () =>
|
||||||
{
|
{
|
||||||
const authenticationMetaData: QAuthenticationMetaData = await qController.getAuthenticationMetaData();
|
|
||||||
setAuthenticationMetaData(authenticationMetaData);
|
|
||||||
|
|
||||||
if (authenticationMetaData.type === "AUTH_0")
|
if (authenticationMetaData.type === "AUTH_0")
|
||||||
{
|
{
|
||||||
await auth0SetupSession();
|
await auth0SetupSession();
|
||||||
@ -134,7 +135,7 @@ export default function App()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
** call approprite logout function based on authentication meta data type
|
** call appropriate logout function based on authentication meta data type
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
function doLogout()
|
function doLogout()
|
||||||
{
|
{
|
||||||
@ -157,7 +158,7 @@ export default function App()
|
|||||||
}
|
}
|
||||||
|
|
||||||
const [controller, dispatch] = useMaterialUIController();
|
const [controller, dispatch] = useMaterialUIController();
|
||||||
const {miniSidenav, direction, layout, openConfigurator, sidenavColor} = controller;
|
const {miniSidenav, direction, sidenavColor} = controller;
|
||||||
const [onMouseEnter, setOnMouseEnter] = useState(false);
|
const [onMouseEnter, setOnMouseEnter] = useState(false);
|
||||||
const {pathname} = useLocation();
|
const {pathname} = useLocation();
|
||||||
const [queryParams] = useSearchParams();
|
const [queryParams] = useSearchParams();
|
||||||
@ -450,11 +451,10 @@ export default function App()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let profileRoutes = {};
|
|
||||||
const gravatarBase = "https://www.gravatar.com/avatar/";
|
const gravatarBase = "https://www.gravatar.com/avatar/";
|
||||||
const hash = Md5.hashStr(loggedInUser?.email || "user");
|
const hash = Md5.hashStr(loggedInUser?.email || "user");
|
||||||
const profilePicture = `${gravatarBase}${hash}`;
|
const profilePicture = `${gravatarBase}${hash}`;
|
||||||
profileRoutes = {
|
const profileRoutes = {
|
||||||
type: "collapse",
|
type: "collapse",
|
||||||
name: loggedInUser?.name ?? "Anonymous",
|
name: loggedInUser?.name ?? "Anonymous",
|
||||||
key: "username",
|
key: "username",
|
||||||
|
@ -52,7 +52,7 @@ authenticationMetaDataPromise.then((authenticationMetaData) =>
|
|||||||
function Auth0RouterBody()
|
function Auth0RouterBody()
|
||||||
{
|
{
|
||||||
const {renderAppWrapper} = useAuth0AuthenticationModule({});
|
const {renderAppWrapper} = useAuth0AuthenticationModule({});
|
||||||
return (renderAppWrapper(authenticationMetaData, null));
|
return (renderAppWrapper(authenticationMetaData));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -61,10 +61,10 @@ authenticationMetaDataPromise.then((authenticationMetaData) =>
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
function OAuth2RouterBody()
|
function OAuth2RouterBody()
|
||||||
{
|
{
|
||||||
const {renderAppWrapper} = useOAuth2AuthenticationModule({});
|
const {renderAppWrapper} = useOAuth2AuthenticationModule({inOAuthContext: false});
|
||||||
return (renderAppWrapper(authenticationMetaData, (
|
return (renderAppWrapper(authenticationMetaData, (
|
||||||
<MaterialUIControllerProvider>
|
<MaterialUIControllerProvider>
|
||||||
<App />
|
<App authenticationMetaData={authenticationMetaData} />
|
||||||
</MaterialUIControllerProvider>
|
</MaterialUIControllerProvider>
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -78,7 +78,7 @@ authenticationMetaDataPromise.then((authenticationMetaData) =>
|
|||||||
const {renderAppWrapper} = useAnonymousAuthenticationModule({});
|
const {renderAppWrapper} = useAnonymousAuthenticationModule({});
|
||||||
return (renderAppWrapper(authenticationMetaData, (
|
return (renderAppWrapper(authenticationMetaData, (
|
||||||
<MaterialUIControllerProvider>
|
<MaterialUIControllerProvider>
|
||||||
<App />
|
<App authenticationMetaData={authenticationMetaData} />
|
||||||
</MaterialUIControllerProvider>
|
</MaterialUIControllerProvider>
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
@ -41,11 +41,11 @@ interface Props
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
** hook for working with the Auth0 authentication module
|
** hook for working with the Auth0 authentication module
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
export default function useAuth0AuthenticationModule({setIsFullyAuthenticated, setLoggedInUser, setEarlyReturnForAuth}: Props)
|
export default function useAuth0AuthenticationModule({setIsFullyAuthenticated, setLoggedInUser}: Props)
|
||||||
{
|
{
|
||||||
const {user: auth0User, getAccessTokenSilently: auth0GetAccessTokenSilently, logout: useAuth0Logout} = useAuth0();
|
const {user: auth0User, getAccessTokenSilently: auth0GetAccessTokenSilently, logout: useAuth0Logout} = useAuth0();
|
||||||
|
|
||||||
const [cookies, setCookie, removeCookie] = useCookies([SESSION_UUID_COOKIE_NAME]);
|
const [cookies, removeCookie] = useCookies([SESSION_UUID_COOKIE_NAME]);
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
@ -119,12 +119,7 @@ export default function useAuth0AuthenticationModule({setIsFullyAuthenticated, s
|
|||||||
if (shouldStoreNewToken(accessToken, lsAccessToken))
|
if (shouldStoreNewToken(accessToken, lsAccessToken))
|
||||||
{
|
{
|
||||||
console.log("Sending accessToken to backend, requesting a sessionUUID...");
|
console.log("Sending accessToken to backend, requesting a sessionUUID...");
|
||||||
const {uuid: newSessionUuid, values} = await qController.manageSession(accessToken, null);
|
const {uuid: values} = await qController.manageSession(accessToken, null);
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// the request to the backend should send a header to set the cookie, so we don't need to do it ourselves. //
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// setCookie(SESSION_UUID_COOKIE_NAME, newSessionUuid, {path: "/"});
|
|
||||||
|
|
||||||
localStorage.setItem("accessToken", accessToken);
|
localStorage.setItem("accessToken", accessToken);
|
||||||
localStorage.setItem("sessionValues", JSON.stringify(values));
|
localStorage.setItem("sessionValues", JSON.stringify(values));
|
||||||
@ -199,7 +194,7 @@ export default function useAuth0AuthenticationModule({setIsFullyAuthenticated, s
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
**
|
**
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
const renderAppWrapper = (authenticationMetaData: QAuthenticationMetaData, children: JSX.Element): JSX.Element =>
|
const renderAppWrapper = (authenticationMetaData: QAuthenticationMetaData): JSX.Element =>
|
||||||
{
|
{
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
let domain: string = authenticationMetaData.data.baseUrl;
|
let domain: string = authenticationMetaData.data.baseUrl;
|
||||||
@ -225,6 +220,15 @@ export default function useAuth0AuthenticationModule({setIsFullyAuthenticated, s
|
|||||||
domain = domain.replace(/\/$/, "");
|
domain = domain.replace(/\/$/, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
** simple Functional Component to wrap the <App> and pass the authentication-
|
||||||
|
** MetaData prop in, so a simple Component can be passed into ProtectedRoute
|
||||||
|
***************************************************************************/
|
||||||
|
function WrappedApp()
|
||||||
|
{
|
||||||
|
return <App authenticationMetaData={authenticationMetaData} />
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Auth0ProviderWithRedirectCallback
|
<Auth0ProviderWithRedirectCallback
|
||||||
domain={domain}
|
domain={domain}
|
||||||
@ -232,7 +236,7 @@ export default function useAuth0AuthenticationModule({setIsFullyAuthenticated, s
|
|||||||
audience={audience}
|
audience={audience}
|
||||||
redirectUri={`${window.location.origin}/`}>
|
redirectUri={`${window.location.origin}/`}>
|
||||||
<MaterialUIControllerProvider>
|
<MaterialUIControllerProvider>
|
||||||
<ProtectedRoute component={App} />
|
<ProtectedRoute component={WrappedApp} />
|
||||||
</MaterialUIControllerProvider>
|
</MaterialUIControllerProvider>
|
||||||
</Auth0ProviderWithRedirectCallback>
|
</Auth0ProviderWithRedirectCallback>
|
||||||
);
|
);
|
||||||
|
@ -23,7 +23,7 @@ import {QAuthenticationMetaData} from "@kingsrook/qqq-frontend-core/lib/model/me
|
|||||||
import {SESSION_UUID_COOKIE_NAME} from "App";
|
import {SESSION_UUID_COOKIE_NAME} from "App";
|
||||||
import Client from "qqq/utils/qqq/Client";
|
import Client from "qqq/utils/qqq/Client";
|
||||||
import {useCookies} from "react-cookie";
|
import {useCookies} from "react-cookie";
|
||||||
import {AuthProvider, useAuth} from "react-oidc-context";
|
import {AuthContextProps, AuthProvider, useAuth} from "react-oidc-context";
|
||||||
import {useNavigate, useSearchParams} from "react-router-dom";
|
import {useNavigate, useSearchParams} from "react-router-dom";
|
||||||
|
|
||||||
const qController = Client.getInstance();
|
const qController = Client.getInstance();
|
||||||
@ -33,16 +33,22 @@ interface Props
|
|||||||
setIsFullyAuthenticated?: (is: boolean) => void;
|
setIsFullyAuthenticated?: (is: boolean) => void;
|
||||||
setLoggedInUser?: (user: any) => void;
|
setLoggedInUser?: (user: any) => void;
|
||||||
setEarlyReturnForAuth?: (element: JSX.Element | null) => void;
|
setEarlyReturnForAuth?: (element: JSX.Element | null) => void;
|
||||||
|
inOAuthContext: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
** hook for working with the OAuth2 authentication module
|
** hook for working with the OAuth2 authentication module
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
export default function useOAuth2AuthenticationModule({setIsFullyAuthenticated, setLoggedInUser, setEarlyReturnForAuth}: Props)
|
export default function useOAuth2AuthenticationModule({setIsFullyAuthenticated, setLoggedInUser, setEarlyReturnForAuth, inOAuthContext}: Props)
|
||||||
{
|
{
|
||||||
const authOidc = useAuth();
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// the useAuth hook should only be called if we're inside the <AuthProvider> element //
|
||||||
|
// so on the page that uses this hook to call renderAppWrapper, we aren't in that //
|
||||||
|
// element/context, thus, don't call that hook. //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
const authOidc: AuthContextProps | null = inOAuthContext ? useAuth() : null;
|
||||||
|
|
||||||
const [cookies, setCookie, removeCookie] = useCookies([SESSION_UUID_COOKIE_NAME]);
|
const [cookies, removeCookie] = useCookies([SESSION_UUID_COOKIE_NAME]);
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@ -84,7 +90,7 @@ export default function useOAuth2AuthenticationModule({setIsFullyAuthenticated,
|
|||||||
if (sessionUuid)
|
if (sessionUuid)
|
||||||
{
|
{
|
||||||
console.log(`we have session UUID: ${sessionUuid} - validating it...`);
|
console.log(`we have session UUID: ${sessionUuid} - validating it...`);
|
||||||
const {uuid: newSessionUuid, values} = await qController.manageSession(null, sessionUuid, null);
|
const {values} = await qController.manageSession(null, sessionUuid, null);
|
||||||
|
|
||||||
setIsFullyAuthenticated(true);
|
setIsFullyAuthenticated(true);
|
||||||
qController.setGotAuthentication();
|
qController.setGotAuthentication();
|
||||||
@ -98,7 +104,7 @@ export default function useOAuth2AuthenticationModule({setIsFullyAuthenticated,
|
|||||||
console.log(authOidc);
|
console.log(authOidc);
|
||||||
localStorage.setItem(preSigninRedirectPathnameKey, window.location.pathname);
|
localStorage.setItem(preSigninRedirectPathnameKey, window.location.pathname);
|
||||||
setEarlyReturnForAuth(<div>Signing in...</div>);
|
setEarlyReturnForAuth(<div>Signing in...</div>);
|
||||||
authOidc.signinRedirect();
|
authOidc?.signinRedirect();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -151,7 +157,7 @@ export default function useOAuth2AuthenticationModule({setIsFullyAuthenticated,
|
|||||||
{
|
{
|
||||||
qController.clearAuthenticationMetaDataLocalStorage();
|
qController.clearAuthenticationMetaDataLocalStorage();
|
||||||
removeCookie(SESSION_UUID_COOKIE_NAME, {path: "/"});
|
removeCookie(SESSION_UUID_COOKIE_NAME, {path: "/"});
|
||||||
authOidc.signoutRedirect();
|
authOidc?.signoutRedirect();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user