SSR下的Auth0

问题描述 投票:0回答:1

我的代码中有以下钩子,可以为我执行 Auth0 重定向。在大多数情况下,这是 Auth0 人员一次性发布的一个示例,以及他们的

@auth0/auth0-spa-js
库。

const DEFAULT_REDIRECT_CALLBACK = () =>
  window.history.replaceState({}, document.title, window.location.pathname);

export const Auth0Context = createContext();
export const useAuth0 = () => useContext(Auth0Context);
export const Auth0Provider = ({
  children,
  onRedirectCallback = DEFAULT_REDIRECT_CALLBACK,
  ...initOptions
}) => {
  const [isAuthenticated, setIsAuthenticated] = useState();
  const [user, setUser] = useState();
  const [auth0Client, setAuth0] = useState();
  const [loading, setLoading] = useState(true);
  const [popupOpen, setPopupOpen] = useState(false);

  useEffect(() => {
    const initAuth0 = async () => {
      const auth0FromHook = await createAuth0Client(initOptions);
      setAuth0(auth0FromHook);

      if (
        window.location.search.includes('code=') &&
        window.location.search.includes('state=')
      ) {
        const { appState } = await auth0FromHook.handleRedirectCallback();
        onRedirectCallback(appState);
      }

      const isAuthenticated = await auth0FromHook.isAuthenticated();

      setIsAuthenticated(isAuthenticated);

      if (isAuthenticated) {
        const user = await auth0FromHook.getUser();
        setUser(user);
        localStorage.setItem('user', user.email);
        const token = await auth0FromHook.getTokenSilently();
        localStorage.setItem('token', token);
      }

      setLoading(false);
    };
    initAuth0();
    // eslint-disable-next-line
  }, []);

  const loginWithPopup = async (params = {}) => {
    setPopupOpen(true);
    try {
      await auth0Client.loginWithPopup(params);
    } catch (error) {
      console.error(error);
    } finally {
      setPopupOpen(false);
    }
    const user = await auth0Client.getUser();
    setUser(user);
    setIsAuthenticated(true);
  };

  const handleRedirectCallback = async () => {
    setLoading(true);
    await auth0Client.handleRedirectCallback();
    const user = await auth0Client.getUser();
    setLoading(false);
    setIsAuthenticated(true);
    setUser(user);
  };

  return (
    <Auth0Context.Provider
      value={{
        isAuthenticated,
        user,
        loading,
        popupOpen,
        loginWithPopup,
        handleRedirectCallback,
        getIdTokenClaims: (...p) => auth0Client.getIdTokenClaims(...p),
        loginWithRedirect: (...p) => auth0Client.loginWithRedirect(...p),
        getTokenSilently: (...p) => auth0Client.getTokenSilently(...p),
        getTokenWithPopup: (...p) => auth0Client.getTokenWithPopup(...p),
        logout: (...p) => auth0Client.logout(...p)
      }}
    >
      {children}
    </Auth0Context.Provider>
  );
};

此代码工作正常,仅适用于

history
location
,它使用
window.history
window.location
。因此,该代码在服务器端渲染下不起作用。

我需要这个功能有几个不同的原因,首先是:

const App = () => {
  const { loading } = useAuth0();

  if (loading) {
    return <div>Loading...</div>;
  }

  return (
    <Switch>
      <Redirect
        from='/:url*(/+)'
        to={
          typeof window === 'object' && window.location
            ? window.location.pathname.slice(0, -1)
            : '/'
        }
      />
      <Route exact path='/' component={Deals} />
      <PrivateRoute exact path='/draft' component={Draft} />
      <PrivateRoute exact path='/cabinet' component={Cabinet} />
      <PrivateRoute exact path='/profile' component={Profile} />
      <PrivateRoute
        path='/deal/:id'
        exact
        component={(props) => <Draft {...props} />}
      />
    </Switch>
  );
};

我确实有上下文的历史记录,所以我只需要一种将其传递给

useAuth0
函数的方法。

const { store, history } = configureStore();

const MOUNT_NODE = document.getElementById('root');
const AUTH0_SCOPE = 'openid profile email';

const onRedirectCallback = (appState) => {
  history.push(
    appState && appState.targetUrl
      ? appState.targetUrl + (appState.qs || '')
      : window.location.pathname
  );
};

const Application = (
  <Suspense fallback={<Loading />}>
    <CookiesProvider>
      <Auth0Provider
        domain={process.env.REACT_APP_AUTH0_DOMAIN}
        audience={process.env.REACT_APP_AUTH0_AUDIENCE}
        scope={AUTH0_SCOPE}
        client_id={process.env.REACT_APP_AUTH0_CLIENT_ID}
        redirect_uri={window.location.origin}
        onRedirectCallback={onRedirectCallback}
      >
        <Provider store={store}>
          <ConnectedRouter history={history}>
            <Frontload noServerRender={true}>
              <App />
            </Frontload>
          </ConnectedRouter>
        </Provider>
      </Auth0Provider>
    </CookiesProvider>
  </Suspense>
);

有什么想法如何使用类似于

useLocation
useHistory
中的
react-router-dom
挂钩的东西重写此函数,或者让
useAuth0
在 SSR 上工作吗?

谢谢你

reactjs react-router-dom server-side-rendering auth0
1个回答
0
投票

看来现代的

@auth0/auth0-react
库已经以与SSR兼容的方式实现了
useAuth()
。一路走好 Auth0!

© www.soinside.com 2019 - 2024. All rights reserved.