【问题标题】:How to use Auth0 with react-admin?如何将 Auth0 与 react-admin 一起使用?
【发布时间】:2020-04-22 17:54:34
【问题描述】:

我正在尝试在 react-admin v3 应用程序中使用 Auth0 实现身份验证。我需要实现一个与 Auth0 对话的authProvider。这听起来应该在某处可用,但我能找到的最接近的是 https://github.com/alexicum/merge-admin/blob/master/src/Auth/index.js,它大约有 2 年的历史(从那时起 SDK 发生了变化)。

是否有一个 Auth0 authProvider 我可以重用,还是我必须自己实现它?

谢谢!

【问题讨论】:

  • 你有什么运气吗?我不是 React 开发人员,并且即将尝试同样的事情,我很惊讶你的问题是我能找到的最相关的事情。
  • @Hastarin 不是真的,我必须自己开发一个。它仍然很老套,并且 Auth0 和 react-admin AuthProvider 抽象在某些地方存在漏洞。它现在正在工作,但我仍在寻找更好的解决方案。迄今为止最好的是github.com/alexicum/merge-admin/blob/master/src/Auth/index.js。

标签: reactjs auth0 react-admin


【解决方案1】:

为了参考,这里是一个将 react admin 与 auth0-react 包集成的示例

index.js

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

ReactDOM.render(
  <Auth0Provider
    domain="XXXXX.auth0.com"
    clientId="XXXXX"
    audience="https://XXXXX"
    redirectUri={window.location.origin}
  >
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </Auth0Provider>,
  document.getElementById("root")
);

App.js

import { withAuth0, withAuthenticationRequired } from "@auth0/auth0-react";
import ApolloClient from "apollo-boost";

// I'm using Hasura w/ JWT Auth, so here's an example of how to set Authorization Header
async componentDidMount() {
    const token = await this.props.auth0.getAccessTokenSilently();

    const client = new ApolloClient({
      uri: "https://HASURA_URL/v1/graphql",
      headers: {
        Authorization: `Bearer ${token}`
      },
    });

    buildHasuraProvider({ client }).then((dataProvider) =>
      this.setState({ dataProvider })
    );
  }

export default withAuthenticationRequired(withAuth0(App));

【讨论】:

  • 虽然这不符合 react-admin 处理身份验证的自以为是的方式,但这当然非常简单,到目前为止看起来很可靠。谢谢!
【解决方案2】:

我已经使用 Auth0 和 react-admin 的身份验证方式创建了一个示例应用程序

https://github.com/spintech-software/react-admin-auth0-example

这是供参考的身份验证提供程序代码

import authConfig from "./authConfig";
import {Auth0Client} from '@auth0/auth0-spa-js';

const auth0 = new Auth0Client({
    domain: authConfig.domain,
    client_id: authConfig.clientID,
    cacheLocation: 'localstorage',
    useRefreshTokens: true
});

const CallbackURI = "http://localhost:3000/login"

export default {
    // called when the user attempts to log in
    login: (url) => {
        if (typeof url === 'undefined') {
            return auth0.loginWithRedirect({
                redirect_uri: CallbackURI
            })
        }
        return auth0.handleRedirectCallback(url.location);
    },
    // called when the user clicks on the logout button
    logout: () => {
        return auth0.isAuthenticated().then(function (isAuthenticated) {
            if (isAuthenticated) { // need to check for this as react-admin calls logout in case checkAuth failed
                return auth0.logout({
                    redirect_uri: window.location.origin,
                    federated: true // have to be enabled to invalidate refresh token
                });
            }
            return Promise.resolve()
        })
    },
    // called when the API returns an error
    checkError: ({status}) => {
        if (status === 401 || status === 403) {
            return Promise.reject();
        }
        return Promise.resolve();
    },
    // called when the user navigates to a new location, to check for authentication
    checkAuth: () => {
        return auth0.isAuthenticated().then(function (isAuthenticated) {
            if (isAuthenticated) {
                return Promise.resolve();
            }
            return auth0.getTokenSilently({
                redirect_uri: CallbackURI
            })
        })
    },
    // called when the user navigates to a new location, to check for permissions / roles
    getPermissions: () => {
        return Promise.resolve()
    },
};

【讨论】:

    【解决方案3】:

    用auth0原生登录包裹react-admin应用,然后提供react-admindataProvider一个http客户端,读取auth0存储在本地存储中的jwt令牌会更方便。

    【讨论】:

      【解决方案4】:

      我的答案是遵循 react-admin 方法,我使用它的authProvider,如下所示。主要有两个步骤:

      • 从useAuth0钩子获取需要的数据。
      • 将authProvider 转换为接受上述值的函数,并返回一个类似于默认值的对象。
      // In App.js
      
      import authProvider from './providers/authProvider';// my path is changed a bit
      
      const App = () => {
        const {
          isAuthenticated,
          logout,
          loginWithRedirect,
          isLoading,
          error,
          user,
        } = useAuth0();
        const customAuthProvider = authProvider({
          isAuthenticated,
          loginWithRedirect,
          logout,
          user,
        });
      
        return (
            <Admin
              {...otherProps}
              authProvider={customAuthProvider}
            >
            {...children}
            </Admin>
          );
      }
      
      // My authProvider.js
      
      const authProvider = ({
        isAuthenticated,
        loginWithRedirect,
        logout,
        user,
      }) => ({
        login: loginWithRedirect,
        logout: () => logout({ returnTo: window.location.origin }),
        checkError: () => Promise.resolve(),
        checkAuth: () => (isAuthenticated ? Promise.resolve() : Promise.reject()),
        getPermissions: () => Promise.reject('Unknown method'),
        getIdentity: () =>
          Promise.resolve({
            id: user.id,
            fullName: user.name,
            avatar: user.picture,
          }),
      });
      
      export default authProvider;
      

      就是这样。

      【讨论】:

        猜你喜欢
        • 2018-05-31
        • 1970-01-01
        • 2020-11-19
        • 1970-01-01
        • 1970-01-01
        • 2019-04-04
        • 2019-09-23
        • 2018-08-30
        • 2019-02-04
        相关资源
        最近更新 更多