如何将 Auth0 与 react-admin 一起使用?

Posted

技术标签:

【中文标题】如何将 Auth0 与 react-admin 一起使用?【英文标题】:How to use Auth0 with 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。 【参考方案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;

就是这样。

【讨论】:

以上是关于如何将 Auth0 与 react-admin 一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

登录前后将 react-admin 应用与捆绑包拆分的代码

Auth0-如何与 Flutter 一起使用

如何将 django rest api 中的用户与 Auth0 同步

如何将 Auth0 与 .net 核心 API 和 Angular 一起使用?

将 Auth0 与科尔多瓦 jQuery 移动应用程序集成

react-admin 编辑等待响应