使用Auth0 React SDK获取访问令牌和使用PKCE的授权代码流会导致无限循环

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

我已经使用 PKCE 实现了 Auth0 React SDK 以及授权代码流,以在我的 React 单页应用程序 (SPA) 中获取访问令牌,以便对受保护的后端路由进行 API 调用。

我选择使用 PKCE 的授权代码流程,因为 SPA 被视为公共应用程序,而不是机密应用程序。因此,我们无法使用标准授权代码流程获取访问令牌。

当我使用loginWithRedirect()函数时,用户通过身份验证后一切都会顺利进行。但是,在使用 PKCE 实现授权代码流程(涉及生成用于使用代码验证程序和代码质询进行用户身份验证和授权的链接)后,用户会被重复重定向到重定向 URL。此外,重定向的链接每次都包含不同的代码查询参数值。

这里是使用 PKCE 的授权代码流程的链接

下面是我的代码和演示问题的屏幕截图。

Auth0Provider 设置

import { Auth0Provider } from "@auth0/auth0-react";

import React from "react";

export const Auth0ProviderComponent = ({
  children,
}: {
  children: React.ReactNode;
}) => {
  // const navigate = useNavigate();

  const domain = import.meta.env.VITE_AUTH0_ISSUER_BASE_URL;
  const clientId = import.meta.env.VITE_AUTH0_CLIENT_ID;
  const redirectUri = import.meta.env.VITE_BASE_FRONTEND_URL;

  if (!(domain && clientId && redirectUri)) {
    return null;
  }

  return (
    <Auth0Provider
      domain={domain}
      clientId={clientId}
      authorizationParams={{
        redirect_uri: redirectUri,
      }}
    >
      {children}
    </Auth0Provider>
  );
};

main.tsx

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";
import "./index.css";
import { Auth0ProviderComponent } from "./components/Auth0ProviderComponent.tsx";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <Auth0ProviderComponent>
      <App />
    </Auth0ProviderComponent>
  </React.StrictMode>
);

App.tsx

import { useEffect, useState } from "react";
import "./App.css";
import { useAuth0 } from "@auth0/auth0-react";
import CryptoJS from "crypto-js";

function App() {
  const { isAuthenticated, isLoading, user } = useAuth0();

  function base64URLEncode(input: any) {
    const words = CryptoJS.enc.Utf8.parse(input);
    const base64 = CryptoJS.enc.Base64.stringify(words);

    return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
  }

  function sha256(input: any) {
    const words = CryptoJS.enc.Utf8.parse(input);
    const hash = CryptoJS.SHA256(words);

    return hash.toString(CryptoJS.enc.Base64);
  }

  useEffect(() => {
    if (!isLoading && !isAuthenticated && !user) {
      //Create verifier
      const randomBytes = CryptoJS.lib.WordArray.random(32); // 32 bytes
      const verifier = base64URLEncode(
        randomBytes.toString(CryptoJS.enc.Base64)
      );

      // Use the previously generated verifier to create the challenge code
      const challenge = base64URLEncode(sha256(verifier));

      //Generate link to authenticate and authorize users
      const config = {
        response_type: "code",
        client_id: import.meta.env.VITE_AUTH0_CLIENT_ID,
        code_challenge: challenge,
        code_challenge_method: "S256",
        redirect_uri: import.meta.env.VITE_BASE_FRONTEND_URL,
        audience: import.meta.env.VITE_AUTH0_CLIENT_AUDIENCE,
        scope: "read:user-resources",
      };
      const generatedLink = `https://${
        import.meta.env.VITE_AUTH0_ISSUER_BASE_URL
      }/authorize?${new URLSearchParams(config).toString()}`;

      //Use the link
      window.location.href = generatedLink;
    }

    if (!isLoading && isAuthenticated && user) {
      alert("successfully log in");
    }
  }, [isAuthenticated, isLoading, user]);
  return (
    <>
      <h1>Home page</h1>
    </>
  );
}

export default App;

无限循环,其中用户使用不同的代码查询值重定向到此重定向 uri。

当我记录 isAuthenticated 和用户状态时,它们总是分别为 false 和未定义。

我非常感谢您的帮助。我已经被这个 bug 困住了很长一段时间了。非常感谢。

reactjs authentication authorization auth0 pkce
1个回答
0
投票

我认为它会在无限循环中不断进行身份验证,因为您将 isloading 添加到 useEffect 依赖项数组中。这只是意味着每次您尝试登录时,它将开始加载,然后 useEffect 将再次工作并生成另一个链接

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