react-admin-firebase icon indicating copy to clipboard operation
react-admin-firebase copied to clipboard

Restricting access with permissions

Open yusrimathews opened this issue 5 years ago • 2 comments

I've set user permissions in Firebase using "setCustomUserClaims" and "authProvider.getPermissions()" returns the permissions array I've set. However, restricting access to resources or views are not working:

https://marmelab.com/react-admin/Authorization.html

<Admin
    dataProvider={dataProvider}
    authProvider={authProvider}
>
    {permissions => [
        // Restrict access to the edit and remove views to admin only (tried "permissions.includes('admin')" as well)
        <Resource
            name="customers"
            list={VisitorList}
            edit={permissions === 'admin' ? VisitorEdit : null}
            icon={VisitorIcon}
        />,
        // Only include the categories resource for admin users (tried "permissions.includes('admin')" as well)
        permissions === 'admin'
            ? <Resource name="categories" list={CategoryList} edit={CategoryEdit} icon={CategoryIcon} />
            : null,
    ]}
</Admin>

Better yet, it would be great to block login completely based on permissions i.e. only admin is able to log in

yusrimathews avatar Dec 30 '20 17:12 yusrimathews

Hi @yusrimathews,

The way permissions is set up is as an Array of claims so try using

permissions.includes('admin')

Restricting Login

As discussed in #140, you can wrap the authProvider, so that it require's that the user has the 'admin' claim set (as shown below).

const authProvider = FirebaseAuthProvider(firebaseConfig, options);
const dataProvider = FirebaseDataProvider(firebaseConfig, options);

// Use this just like the normal auth provider
const myAuthProvider = {
  // Copy all authprovider functionality
  ...authProvider,
  // Wrap the login and check for custom claims
  login: async (params) => {
    const user = await authProvider.login(params);
    // getPermissions is how when get the custom claims for the logged in user
    const claims = await authProvider.getPermissions();
    const isAdmin = Array.isArray(claims) && claims.includes("admin");
    if (isAdmin) {
      return user;
    }
    // Make sure user is logged out, if not an admin
    await authProvider.logout()
    throw new Error("Login error, invalid permissions");
  },
};

Cheers, Ben

benwinding avatar Jan 03 '21 22:01 benwinding

Thanks @benwinding 🥇

Using firebase v8.7.x, the above worked for me with a few small tweaks:

// ...
const { scope } = await authProvider.getPermissions(); // get claims.scope
// scope looks something like ["USER", "ADMIN"]
return Array.isArray(scope) && scope.includes('ADMIN');
// ...

scraggo avatar Jul 02 '21 22:07 scraggo