Authorise based on Roles
In this tutorial, we will explore how to implement user role authentication within your MagicJS application.
Before moving forward, it's essential to confirm that user authentication has been properly configured in your MagicJS application, as outlined in the previous section. We'll be utilizing the same files in this tutorial, so ensure that authentication is in place.
If you're unfamiliar with user authentication, please refer Authenticate Users covering the necessary details regarding user authentication setup.
Implementing Role-Based Features
Implement a role-based feature where only users with a specific role can access certain functionalities.
For example, we'll create a "Tell Me a Joke" button that displays a joke, but only users with the "joker" role are allowed to view it.
Backend Logic
1. Creating the "Tell Me a Joke" API
Create a backend file inside the
main-features
folder.Name the file as '
get-joke
'.Add a joke to return.
Implement role-based access control in the backend logic. Users without the required role will receive a message indicating they are not authorized to view the joke.
Refer the below snippet:
import { createBackendFunction, useFunctionContext } from "@magicjs.dev/backend"
export default createBackendFunction(async function () {
const ctx = useFunctionContext(this)
if (ctx.isAuthenticated === false) {
return "You have to sign in first"
}
if (await ctx.isCurrentUserInAnyRoles(["joker"]) === true) {
return "What do you call a magic dog? A Labracadabrador."
} else {
return "You are not a joker."
}
})
In the above code,
ctx.isAuthenticated
checks if the user is authenticated. If not, it returns a message indicating that the user needs to sign in.Then,
ctx.isCurrentUserInAnyRoles(["joker"])
checks if the current user has the role "joker". If true, it returns a joke message. If not, it returns a message indicating that the user is not a joker.
Invoke the API in a button.
Add a button in the '
home.tsx
' file and label it as Tell me a joke.Call the '
getJokeServer
' in the button as shown in the below code.
import React from "react"
import { Button } from "antd"
import { useLogin } from "@magicjs.dev/frontend"
import loginServer from "./login.server"
import getMyNameServer from "./get-my-name.server"
import getJokeServer from "./get-joke.server"
export default function Component(props: any) {
const { current, logout } = useLogin()
return (
<div>
<h1>{`Current User: ${current?.currentUser?.name}`}</h1>
<Button onClick={() => loginServer('John')}>
Login
</Button>
<Button onClick={() => getMyNameServer().then((name) => alert(name))}>
Call Protected Backend
</Button>
{
current.isAuthenticated === true ? (
<Button onClick={() => logout()}>
Logout
</Button>
) : null
}
<div>
<Button onClick={() => getJokeServer().then((name) => alert(name))}>
Tell me a Joke
</Button>
</div>
</div>
)
}
Tell me a Joke button calls the
getJokeServer
function imported fromget-joke.server
and alerts the returned joke when clicked.

2. Role Assignment and Removal
To enable users to add or remove their roles, we'll create two backend APIs for role assignment and removal. Users can click the "Add Role" button to assign the "joker" role to themselves and subsequently remove it using the "Remove Role" button.
Create 2 backed files and name them 'add-role' and remove-role' respectively.
Refer the below codes:
import { createBackendFunction, useFunctionContext, utils } from "@magicjs.dev/backend"
export default createBackendFunction(async function () {
const ctx = useFunctionContext(this)
await utils.assignRoleToUser(ctx.currentUser._id, 'joker');
return "Message from server"
})
import { createBackendFunction, useFunctionContext, utils } from "@magicjs.dev/backend"
export default createBackendFunction(async function () {
const ctx = useFunctionContext(this)
await utils.unassignRoleFromUser(ctx.currentUser._id, 'joker');
return "Message from server"
})
Invoke the add-role and remove-role with respective buttons in
home.tsx
.
Refer the code below.
import React from "react"
import { Button } from "antd"
import { useLogin } from "@magicjs.dev/frontend"
import loginServer from "./login.server"
import getMyNameServer from "./get-my-name.server"
import getJokeServer from "./get-joke.server"
import addRoleServer from "./add-role.server"
import removeRoleServer from "./remove-role.server"
export default function Component(props: any) {
const { current, logout } = useLogin()
return (
<div>
<h1>{`Current User: ${current?.currentUser?.name}`}</h1>
<Button onClick={() => loginServer('John')}>
Login
</Button>
<Button onClick={() => getMyNameServer().then((name) => alert(name))}>
Call Protected Backend
</Button>
{
current.isAuthenticated === true ? (
<Button onClick={() => logout()}>
Logout
</Button>
) : null
}
<div>
<Button onClick={() => addRoleServer().then(() => alert('Role added'))}>
Add Role
</Button>
<Button onClick={() => getJokeServer().then((name) => alert(name))}>
Tell me a Joke
</Button>
<Button onClick={() => removeRoleServer().then(() => alert('Role removed'))}>
Remove Role
</Button>
</div>
</div>
)
}
Add Role button calls the
addRoleServer
function imported fromadd-role.server
and assigns the role 'joker' to the current user when clicked.Remove Role button calls the
removeRoleServer
function imported fromremove-role.server
and unassigns the role 'joker' from the current user when clicked.

Ensuring Frontend Protection
Adding Frontend Protection ensures that frontend components and features are only accessible to users with the requisite roles.
In conjunction with backend role-based access control mechanisms, frontend role checks will be integrated using the isCurrentUserInAnyRoles
function provided by MagicJS.
Add function
isCurrentUserInAnyRoles
in theuseLogin
hook.Wrap the Tell me a joke button inside this function as shown in the below code.
Code:
import React from "react"
import { Button } from "antd"
import { useLogin } from "@magicjs.dev/frontend"
import loginServer from "./login.server"
import getMyNameServer from "./get-my-name.server"
import getJokeServer from "./get-joke.server"
import addRoleServer from "./add-role.server"
import removeRoleServer from "./remove-role.server"
export default function Component(props: any) {
const { current, logout, isCurrentUserInAnyRoles } = useLogin()
return (
<div>
<h1>{`Current User: ${current?.currentUser?.name}`}</h1>
<Button onClick={() => loginServer('John')}>
Login
</Button>
<Button onClick={() => getMyNameServer().then((name) => alert(name))}>
Call Protected Backend
</Button>
{
current.isAuthenticated === true ? (
<Button onClick={() => logout()}>
Logout
</Button>
) : null
}
<div>
<Button onClick={() => addRoleServer().then(() => alert('Role added'))}>
Add Role
</Button>
{
isCurrentUserInAnyRoles(['joker']) === true ? (
<Button onClick={() => getJokeServer().then((name) => alert(name))}>
Tell me a Joke
</Button>
) : (
null
)
}
<Button onClick={() => removeRoleServer().then(() => alert('Role removed'))}>
Remove Role
</Button>
</div>
</div>
)
}

By leveraging user role authentication and role management in your MagicJS application, you can tailor access permissions and enhance security. Empowered with role-based access control, you can customize the user experience and ensure that users interact with features aligned with their roles.
🎉 Congratulations! You've learned how to authenticate a user role seamlessly in MERN.AI using the MagicJS framework.
Last updated