Giter Site home page Giter Site logo

ra-auth-auth0's Introduction

ra-auth-auth0

An auth provider for react-admin which handles authentication via a Auth0 instance.

Documentationโ€‚ Source Codeโ€‚

This repository contains:

  • The actual ra-auth-auth0 package
  • A simple demo app you can run locally to try out ra-auth-auth0 with your own Auth0 instance

Simple Demo

Prerequesites

  • You need to have a Auth0 account

Initial setup

  1. Clone this project

We need to add some minimal configuration to our Auth0 instance to use it. This need to be done from the Auth0 Admin Console.

  1. Go to the Auth0 Dashboard
  2. Select your Auth0 Application (or create a new one)
  3. Add [email protected] user to your Auth0 Application. For this, you need to go to the User Management section and create a new user.
  4. Add admin to the Roles section of your Auth0 Application. Assign [email protected] to the admin role.
  5. Do the same for [email protected] and the user role.
  6. Go to the Applications section of your Auth0 Application and select Settings
  7. Create a single page application with the following settings:
    • Allowed Callback URLs: http://127.0.0.1:8081/auth-callback
    • Allowed Logout URLs: http://127.0.0.1:8081
    • Allowed Web Origins: http://127.0.0.1:8081
    • Allowed Origins (CORS): http://127.0.0.1:8081

If you want to use permissions, you need to add the following to your Auth0 Application as an Action:

exports.onExecutePostLogin = async (event, api) => {
  const namespace = 'https://my-app.example.com';
  if (event.authorization) {
    api.idToken.setCustomClaim(`${namespace}/roles`, event.authorization.roles);
    api.accessToken.setCustomClaim(`${namespace}/roles`, event.authorization.roles);
  }
}

The authProvider exported by this package will look for a claim that has a name with the term role in it and return its value.

For react-admin, you need to setup environment variables. You can do this by creating a .env file in the root of the project. The following variables are required:

VITE_AUTH0_DOMAIN="your-domain.auth0.com"
VITE_AUTH0_CLIENT_ID="your-client-id"
VITE_AUTH0_AUDIENCE="https://your-domain.auth0.com/api/v2/" // optional but recommended for having non opaque tokens
VITE_LOGIN_REDIRECT_URL="http://127.0.0.1:8081/auth-callback"
VITE_LOGOUT_REDIRECT_URL="http://127.0.0.1:8081"
  1. Run make install start to install the dependencies and start the Demo App

Using the Simple Demo

Now that all is configured and running, you can browse to http://127.0.0.1:8081/ to access the React Admin App.

  • Signing in with [email protected] will only grant the user role permissions
  • Signing in with [email protected] will grant full admin role permissions, allowing for instance to see the 'Users' resource in the main menu

Feel free to play around with this demo, along with the Auth0 config, to understand better how it works!

JSON Server API

The demo app uses a JSON Server to provide a REST API. You can find the configuration in the demo-fake-api folder. It shows how use middleware to validate the JWT token via the Auth0 API.

License

This repository and the code it contains are licensed under the MIT License and sponsored by marmelab.

ra-auth-auth0's People

Contributors

adguernier avatar arimet avatar djhi avatar fzaninotto avatar septentrion-730n avatar slax57 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

ra-auth-auth0's Issues

checkAuth should throw an error after the redirect

At the moment, the checkAuth function just redirects, but does not actually return a rejected promise. This often seems to work fine, but it can lead to issues, because under certain conditions, the code continues to execute even after the redirect has started. For example, using requireAuth does not work properly in this case, because it checkAuth just returns normally, so it is assumed that the user is authenticated.

Even worse, this can lead to checkAuth being called again (resulting in a new login attempt), if that is required by specific routes. And even checkError might be called, because we a re not authenticated yet, but some routes might result in backend calls.

Combined, this can result in extremely nasty race conditions, where the login sometimes works, and sometimes doesn't, depending on when the browser decides to stop the execution of JavaScript when the redirect happens. This can also differ between browsers. I don't have any resources, but from my experience, Firefox tends to continue executing JavaScript for longer than Chrome, so the problems are more likely to manifest there.

Also, at the moment, checkAuth doesn't do anything if the redirectOnCheckAuth option is set to false.

In total, I would recommend to add a simple throw new Error() at the end of checkAuth, to handle both the problem after the redirect and the redirectOnCheckAuth === false case properly.

Infinite loop after login (Follow up to #8)

Hi everyone! I followed the solution provided by @OtterTax in #8 and the error still remains. My authclient is the following:

import { Auth0Client } from '@auth0/auth0-spa-js';
import { Auth0AuthProvider } from 'ra-auth-auth0';

export const auth0 = new Auth0Client({
  domain: "OUR_DOMAIN",
  clientId: "OUR_CLIENT_ID",
  cacheLocation: 'localstorage',
  authorizationParams: {
    audience: "OUR_AUDIENCE",
  },
});

export const auth0Provider = Auth0AuthProvider(auth0, {
  logoutRedirectUri: "http://localhost:5173",
});

This is my App.tsx:

import { Admin, defaultTheme } from 'react-admin';
import { BrowserRouter } from 'react-router-dom';
import { PaletteMode } from '@mui/material';

import { reactAdminDataProvider } from './infrastructure/react-admin/reactAdminDataProvider';
import { auth0Provider } from './providers/providers';

const lightTheme = defaultTheme;
const darkTheme = { ...defaultTheme, palette: { mode: 'dark' as PaletteMode } };

export const App = () => {
  return (
    <BrowserRouter>
      <Admin
        dataProvider={reactAdminDataProvider}
        authProvider={auth0Provider}
        theme={lightTheme}
        darkTheme={darkTheme}
      >
        ...
      </Admin>
    </BrowserRouter>
  );
};

I also tested the same code without "authorizationParams" option but the problem still remains, this is my configuration in auth0:
image

Any help resolving this issue would be appreciated, thanks!!!

Invalid State

I am getting an Invalid state when following the documentation. Here is what I have for my code:

image

App.tsx

const auth0 = new Auth0Client({
  domain: import.meta.env.VITE_AUTH0_DOMAIN,
  clientId: import.meta.env.VITE_AUTH0_CLIENT_ID,
  cacheLocation: "localstorage",
  authorizationParams: {
    audience: import.meta.env.VITE_AUTH0_AUDIENCE,
  },
});

const authProvider = Auth0AuthProvider(auth0, {
  loginRedirectUri: import.meta.env.VITE_LOGIN_REDIRECT_URL,
  logoutRedirectUri: import.meta.env.VITE_LOGOUT_REDIRECT_URL,
});

export const App = () => (
  <BrowserRouter>
    <Admin authProvider={authProvider} dashboard={Dashboard}>
      <Resource name="Billing Transactions"></Resource>
    </Admin>
  </BrowserRouter>
);

.env

VITE_AUTH0_DOMAIN="asdfasdf.us.auth0.com"
VITE_AUTH0_CLIENT_ID="asdfasdf"
VITE_AUTH0_AUDIENCE="https://asdfasdf.us.auth0.com/api/v2/"
VITE_LOGIN_REDIRECT_URL="https://mywebsite.com/auth-callback"
VITE_LOGOUT_REDIRECT_URL="https://mywebsite.com"

Auth0 Application URIs

Application Login URI: Blank
Allowed Callback URLs: https://mywebsite.com/auth-callback
Allowed Logout URLs: https://mywebsite.com
Allowed Web Origins: https://mywebsite.com
Allow Cross-Origin Authentication: https://mywebsite.com

Infinite loop after login (Follow up to #4)

This issue is a follow up to issue #4.

I am still experiencing an infinite loop even after I wrap my <App> component in a <BrowserRouter>.

The steps to reproduce are:

  • Create new project with create-react-app.
  • Create a simple <Admin> component by following the instructions here.
  • Add a data provider for auth0.
  • Wrap <App> in <BrowserRouter>.

After a user authenticates, the page goes into an infinite loop.

The auth provider is very simple:

import { Auth0AuthProvider } from 'ra-auth-auth0';
import { Auth0Client } from '@auth0/auth0-spa-js';

const auth0 = new Auth0Client({
    domain: "OUR-DOMAIN",
    clientId: "OUR-CLIENTID",
    cacheLocation: 'localstorage'
});

export const authProvider = Auth0AuthProvider(auth0, {
    loginRedirectUri: "http://localhost:3000",
    logoutRedirectUri: "http://localhost:3000",
});

And here is the <Admin> component:

import { Admin, Resource, ListGuesser } from "react-admin";
import jsonServerProvider from "ra-data-json-server";
import { BrowserRouter } from "react-router-dom";
import { authProvider } from "./authProvider";

const dataProvider = jsonServerProvider("https://jsonplaceholder.typicode.com");

const GFPAdmin = () => (
  <BrowserRouter>
    <Admin dataProvider={dataProvider}
          authProvider={authProvider}>
      <Resource name="posts" list={ListGuesser} />
      <Resource name="comments" list={ListGuesser} />
    </Admin>
  </BrowserRouter>
);

export default GFPAdmin;

Any help resolving this issue would be appreciated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.