Skip to main content

Authorization

FrontHub uses RBAC as a core specification to its authorization system. It is based on roles, permissions, and grants.

This model ensures that you don't have to use business or value objects inside your application to make authorization decisions. Everything you need to do is to define what are the application resources and its permissions, then create your application using them.

Permissions can be defined directly within each micro frontend or inherited from the Application Host. It is also possible to inherit the configuration from the Application Host and customize it before applying it in the micro frontend.

Config

At first, in your front-hub.config.js create a rbac property with the following format.

Basic

front-hub.config.js
module.exports = {
rbac: {
role: (context) => context.user.role // it is the current role,
permissions: {
user: ['create', 'delete'],
password: ['change', 'forgot'],
article: ['read', 'create', 'edit', 'delete']
},
grants: {
guest: ['article:read'],
writer: ['article:*', 'not article:delete', 'password:forgot'],
admin: ['extends writer', 'article:delete', 'user:*', 'password:*']
}
}
}

Properties

role

This property needs to be a function or a string with the current role value. If you choose to use it as a function, it will receive a context object as a parameter.

This context is the same object declared in the application host which has useful data to handle and return the desired role (string)

permissions

An object which allows you to manage and create kinds of permission according to your project.

We recommend you use each permission propriety to assign for a feature in your project, the value of this property should be an array including all kinds of permissions for that feature.

permissions: {
article: ['read', 'create', 'edit', 'delete']
}

In the example above, we have a feature (article) and some kinds of permission assign for this feature

grants

This object allows you to create grants for access (role) and assign it to some permission resource.

  permissions: {
article: ['read', 'create', 'edit', 'delete']
},
grants: {
guest: ['article:read'],
writer: ['article:*', 'not article:delete', 'password:forgot'],
admin: ['extends writer', 'article:delete', 'user:*', 'password:*']
}

In the example above we create a grant (role) called guest and assign the article read permission for this kind of user.

note
  • You may include all permissions for a resource by using article:*
  • Negating by using the expression not before the permission: not article:delete
  • Inheriting all permissions of some role by using the expression extends before the "grants" referenced: extends guest

Usage

useAuthorization

Start using this hook by important in this way:

import { useAuthorization } from '@resultadosdigitais/front-hub/react'

A useAuthorization is a hook that returns two React components. <Allowed /> which is used to wrap up the business rule allowed. <Denied /> is used to wrap up the opposite, business rule denied.

Both components expect a property permission (string) which the value should be some role previously created in the permission object.

Using authorization hook
const Component = () => {
const { Allowed, Denied } = useAuthorization()

return (
<>
<Allowed permission="article:read">Allowed content</Allowed>

<Denied permission="article:create">Denied Content</Denied>
</>
)
}

Additionally, the hook returns two boolean helper functions: isAllowed and isDenied. These functions allow you to programmatically check if a permission is granted or denied, making it easier to conditionally render components based on access rules.

Just like the components above, the functions expect a parameter which the value should be a permission previously defined in the permissions object.

  • isAllowed Returns true if the permission is granted for the current user, otherwise returns false.
  • isDenied Returns true if the permission is denied for the current user, otherwise returns false.
Using boolean helpers from useAuthorization
const Component = () => {
const { isAllowed, isDenied } = useAuthorization()

return (
<>
{isAllowed('article:read') && <div>Allowed content</div>}
{isDenied('article:create') && <div>Denied content</div>}
</>
)
}

Use these functions when you need more flexibility to render components or execute conditional logic based on permissions, without wrapping content in the <Allowed /> or <Denied /> components.

Application Host

In the Application Host configuration, you can optionally implement a common set of permissions that can be inherited by any micro frontend.

The application host
fronthub('configure', {
rbac: {
role: 'admin',
permissions: {
article: ['read', 'create', 'edit', 'delete'],
},
grants: {
guest: ['article:read'],
writer: ['article:*', 'not article:delete', 'password:forgot'],
admin: ['extends writer', 'article:delete', 'user:*', 'password:*'],
},
},
})

We recommend that when requesting these permissions from an API, you first resolve the API call and then pass the result to the configure command.

The application host
fronthub('configure', {
rbac: someApiResult,
})

How to Configure Your MFE to RBAC permissions from Application Host

To enable your MFE to inherit permissions from the Application Host, simply use the default configuration as shown below.

rbac: {
role: () => '',
permissions: {},
grants: {},
}

Local development

For a smoother local development experience, we recommend using the configuration option shown below.

const rbacConfig = {
production: {
role: () => '',
permissions: {},
grants: {},
},
development: {
role: () => 'user',
permissions: {
user: ['create', 'delete', 'read'],
},
grants: {
user: ['user:write'],
},
},
}

module.exports = {
...configuration,
rbac: rbacConfig[process.env.NODE_ENV],
}

This approach allows you to commit a local configuration, eliminating the need to repeatedly modify the default configuration that enables inheritance.

Customizing RBAC permissions from the Application Host

The second method for inheriting permissions from the Application Host involves using a function that accepts two parameters:

  1. manifest: The MFE's manifest

  2. appHostRbac: The RBAC permissions provided by the Application Host

This approach allows you to customize the permissions from the Application Host before applying them to your MFE, offering greater flexibility when needed.

const rbacConfig = {
production: (manifest, appHostRbac) => {
let customRbac

// Somelogic with appHostRbac

return customRbac
},
development: {
role: () => 'user',
permissions: {
user: ['create', 'delete', 'read'],
},
grants: {
user: ['user:write'],
},
},
}

module.exports = {
...configuration,
rbac: rbacConfig[process.env.NODE_ENV],
}