So i tried to make things work with the described example from the react wrapper, also managed to make things work. The problem we have right now is when reloading the app the isAuthenticated is always undefined. We wrapped the Code inside a AppContext wich provides these things for other components and than loads an AuthenticatedApp or UnauthenticatedApp. When flushing the cache and reload the whole Application everything works, but after hitting reload again the isAuthenticated is always undefined. Maybe someone is having the similiar issues.
Code for App:
const loadAuthenticatedApp = () => import('./authenticated-app');
const AuthenticatedApp = React.lazy(loadAuthenticatedApp);
const UnauthenticatedApp = React.lazy(() => import('./unauthenticated-app'));
interface IPrivateApp {
path?: string;
}
const App: React.FC<IPrivateApp> = ({ path, ...rest }) => {
const { isAuthenticated, loginWithRedirect } = useAuth0();
React.useEffect(() => {
const fn = async () => {
console.log(`AUTH STATUS`, isAuthenticated);
if (isAuthenticated === false) {
await loginWithRedirect({
appState: { targetUrl: path },
redirect_uri: '',
});
}
};
fn();
}, [isAuthenticated, loginWithRedirect, path]);
// React.useEffect(() => {
// loadAuthenticatedApp();
// }, []);
return (
<Suspense fallback={<CircularProgress />}>
{isAuthenticated ? <AuthenticatedApp {...rest} /> : <UnauthenticatedApp />}
</Suspense>
);
};
export default App;
And Code for the Provider:
import React, { useState, useEffect, useContext, useLayoutEffect } from 'react';
import createAuth0Client from '@auth0/auth0-spa-js';
import Auth0Client from '@auth0/auth0-spa-js/dist/typings/Auth0Client';
interface Auth0Context {
isAuthenticated: boolean;
user: any;
loading: boolean;
popupOpen: boolean;
loginWithPopup(options: PopupLoginOptions): Promise<void>;
handleRedirectCallback(): Promise<RedirectLoginResult>;
getIdTokenClaims(o?: getIdTokenClaimsOptions): Promise<IdToken>;
loginWithRedirect(o: RedirectLoginOptions): Promise<void>;
getTokenSilently(o?: GetTokenSilentlyOptions): Promise<string | undefined>;
getTokenWithPopup(o?: GetTokenWithPopupOptions): Promise<string | undefined>;
logout(o?: LogoutOptions): void;
}
interface Auth0ProviderOptions {
children: React.ReactElement;
onRedirectCallback?(result: RedirectLoginResult): void;
}
const DEFAULT_REDIRECT_CALLBACK = () => window.history.replaceState({}, document.title, window.location.pathname);
export const Auth0Context = React.createContext<Auth0Context | null>(null);
export const useAuth0 = () => useContext(Auth0Context)!;
export const Auth0Provider = ({
children,
onRedirectCallback = DEFAULT_REDIRECT_CALLBACK,
...initOptions
}: Auth0ProviderOptions & Auth0ClientOptions) => {
const [isAuthenticated, setIsAuthenticated] = useState();
const [user, setUser] = useState();
const [auth0Client, setAuth0] = useState<Auth0Client>();
const [loading, setLoading] = useState(true);
const [popupOpen, setPopupOpen] = useState(false);
useEffect(() => {
const initAuth0 = async () => {
const auth0FromHook = await createAuth0Client(initOptions);
console.log(`SET AUTH0`);
setAuth0(auth0FromHook);
if (window.location.search.includes('?code=')) {
const { appState } = await auth0FromHook.handleRedirectCallback();
onRedirectCallback(appState);
}
const isAuthenticated = await auth0FromHook.isAuthenticated();
setIsAuthenticated(isAuthenticated);
if (isAuthenticated) {
const user = await auth0FromHook.getUser();
setUser(user);
}
setLoading(false);
};
initAuth0();
// eslint-disable-next-line
}, []);
const loginWithPopup = async (o: PopupLoginOptions) => {
setPopupOpen(true);
try {
// non null assertion operator - expression to tell the compiler
// that this could not be null or undefined
// READ MORE: https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#non-null-assertion-operator
await auth0Client!.loginWithPopup(o);
} catch (error) {
console.error(error);
} finally {
setPopupOpen(false);
}
const user = await auth0Client!.getUser();
setUser(user);
setIsAuthenticated(true);
};
const handleRedirectCallback = async () => {
setLoading(true);
const result = await auth0Client!.handleRedirectCallback();
const user = await auth0Client!.getUser();
setLoading(false);
setIsAuthenticated(true);
setUser(user);
return result;
};
return (
<Auth0Context.Provider
value={{
isAuthenticated,
user,
loading,
popupOpen,
loginWithPopup,
handleRedirectCallback,
getIdTokenClaims: (o: getIdTokenClaimsOptions | undefined) => auth0Client!.getIdTokenClaims(o),
loginWithRedirect: (o: RedirectLoginOptions) => auth0Client!.loginWithRedirect(o),
getTokenSilently: (o: GetTokenSilentlyOptions | undefined) => auth0Client!.getTokenSilently(o),
getTokenWithPopup: (o: GetTokenWithPopupOptions | undefined) => auth0Client!.getTokenWithPopup(o),
logout: (o: LogoutOptions | undefined) => auth0Client!.logout(o),
}}
>
{children}
</Auth0Context.Provider>
);
};
And the index.tsx:
render(
<ApolloProvider client={ApolloClient}>
<Router history={history}>
<AppProvider>
<App />
</AppProvider>
</Router>
</ApolloProvider>,
document.getElementById('root') as HTMLElement,
);
Looks like you're checking for isAuthenticated while the SDK is still fetching data from the server. You have to wait loading to be false before doing anything with the sdk:
const { isAuthenticated, loading } = useAuth0();
useEffect(() => {
const doSomething = async () => {
console.log(isAuthenticated);
};
if (!loading) {
doSomething();
}
}, [loading, getTokenSilently]);
I'll close this issue because it's not related to the SDK itself. If you have more questions, feel free to use https://community.auth0.com/ or open an issue in the sample repo: https://github.com/auth0-samples/auth0-react-samples
Same problem. Not saving auth session. Even on auth0-react-samples.
Same here.
I ran into this, and turns out it's due to using Angular's HashLocationStrategy.
Once I ran it without the hash, it worked fine.
Haven't figured out how to get it working with hash.
I had the same problem. After i reload the page i dont want to run createAuth0Client again due to the its duration (30secs aprox). Do you have any suggestion?
@bermichel it shouldn't take 30s to init. Have you checked this? https://github.com/auth0/auth0-spa-js/blob/master/FAQ.md#why-does-the-auth0client-object-take-a-long-time-to-initialize
Your index.tsx needs to be wrapped with <Auth0Provider/> (this is a snippet from their docs):
```// src/index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import { Auth0Provider } from "./react-auth0-spa";
import config from "./auth_config.json";
// A function that routes the user to the right place
// after login
const onRedirectCallback = appState => {
window.history.replaceState(
{},
document.title,
appState && appState.targetUrl
? appState.targetUrl
: window.location.pathname
);
};
ReactDOM.render(
client_id={config.clientId}
redirect_uri={window.location.origin}
onRedirectCallback={onRedirectCallback}
>
,
document.getElementById("root")
);
Anyone else struggling with this, also ensure your application does not use the Auth0 development keys for social login!
In my case the problem was that I was redirecting before waiting for isLoading. I had this:
<PrivateRoute path="/">
<Redirect to={{ pathname: "/foo" }} />
</PrivateRoute>
and needed to update my PrivateRoute component to this:
function PrivateRoute({ children, ...rest }) {
const { isAuthenticated, isLoading } = useAuth0();
if (isLoading) {
return null;
}
return (
<Route
{...rest}
render={({ location }) =>
isAuthenticated ? (
children
) : (
<Redirect
to={{
pathname: "/login",
state: { from: location }
}}
/>
)
}
/>
);
}
Most helpful comment
Anyone else struggling with this, also ensure your application does not use the Auth0 development keys for social login!