如何在 React Router v6.4 加载器和操作中获取 Auth0 访问令牌?

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

如何在 React Router v6.4

actions
loaders
中访问 Auth0 访问令牌,以便调用安全的 API?

我尝试将

getAccessTokenSilently()
方法柯里化到加载器,但我无法在组件外部调用
useAuth0()
钩子(我的路由是在组件外部创建的 如反应路由器文档所建议的)。出于同样的原因,我无法在加载器内调用
useAuth0()
:它不是组件。

我尝试将路由放入组件内(将下面代码中显示的路由移动到

<App/>
组件),但这会导致
useAuth0()
出现错误,必须从
Auth0Provider
内部调用它。

React Router v6的官方 Auth0 指南尚未更新为使用

createBrowserRouter
,并且在其安全 API 示例中没有使用加载器。

这似乎是任何 React Router v6.4 应用程序的基本需求,但我从未找到一个示例来说明如何做到这一点。肯定有人以前这样做过吗?

这是我的应用程序结构:

Auth0ProviderWithNavigate.tsx

interface Auth0ProviderWithNavigateProps {
  children: React.ReactNode;
}

export const Auth0ProviderWithNavigate = ({
  children,
}: Auth0ProviderWithNavigateProps) => {
  if (
    !(
      ENV.VITE_AUTH0_DOMAIN &&
      ENV.VITE_AUTH0_CLIENT_ID &&
      ENV.VITE_AUTH0_CALLBACK_URL
    )
  ) {
    return null;
  }

  return (
    <Auth0Provider
      domain={ENV.VITE_AUTH0_DOMAIN}
      clientId={ENV.VITE_AUTH0_CLIENT_ID}
      authorizationParams={{
        redirect_uri: ENV.VITE_AUTH0_CALLBACK_URL,
      }}
    >
      {children}
    </Auth0Provider>
  );
};

AuthenticationGuard.tsx

import { withAuthenticationRequired } from "@auth0/auth0-react";
import { PageLoader } from "./PageLoader";

interface AuthenticationGuardProps {
  component: React.ComponentType<object>;
}

export const AuthenticationGuard = ({
  component,
}: AuthenticationGuardProps) => {
  const Component = withAuthenticationRequired(component, {
    onRedirecting: () => <PageLoader />,
  });

  return <Component />;
};

main.tsx

const root = document.getElementById("root");

root &&
  ReactDOM.createRoot(root).render(
    <React.StrictMode>
      <AppContextProvider>
        <Auth0ProviderWithNavigate>
          <AppTheme>
            <App />
          </AppTheme>
        </Auth0ProviderWithNavigate>
      </AppContextProvider>
    </React.StrictMode>
  );

App.tsx

const router = createBrowserRouter([
  {
    children: [
      {
        path: "/",
        element: <WelcomePage />,
        errorElement: <ErrorPage />,
      },
      {
        children: [
          {
            id: "edct",
            path: "/edct",
            element: <AuthenticationGuard component={Edct} />,
            errorElement: <ErrorPage />,
            loader: AirportCodesLoader,
          },
        ],
      },
    ],
  },
]);

const App = () => {
  return <RouterProvider router={router} />;
};

export default App;

AirportCodesLoader.tsx

import { LoaderFunction } from "react-router";

export const AirportCodesLoader: LoaderFunction = ({ request }) => {
  const url = new URL(request.url);

  // Use token here to call a REST API using query params
  // from the URL
};
typescript react-router auth0
1个回答
0
投票

是的,虽然在 React 树之外声明路由器配置是常见的做法,但这只是一个建议。在这种情况下,您可以在

App
组件内创建它,以便它可以关闭要传递给路由加载器的
auth0
上下文值的实例。需要接收
auth0
上下文的路由加载器需要柯里化该参数。

示例:

const AirportCodesLoader = (auth0) => ({ params, request }) => {
  ... loader logic ...
};
const App = () => {
  const auth0 = useAuth0();

  const router = React.useMemo(() => { // <-- memoize router reference
    return createBrowserRouter([
      {
        children: [
          {
            path: "/",
            element: <WelcomePage />,
            errorElement: <ErrorPage />,
          },
          {
            children: [
              {
                id: "edct",
                path: "/edct",
                element: <AuthenticationGuard component={Edct} />,
                errorElement: <ErrorPage />,
                loader: AirportCodesLoader(auth0), // <-- pass auth0 to loader
              },
            ],
          },
        ],
      },
    ]);
  }, [auth0]); // <-- auth0 external dependency

  return <RouterProvider router={router} />;
};
© www.soinside.com 2019 - 2024. All rights reserved.