Nuxt authorization: How to implement fine-grained access control
aldin
Posted on January 15, 2024
In this tutorial you will learn how to use Cerbos to add fine-grained access control to any Nuxt web application, simplifying authorization as a result.
Check out a working example of a Cerbos integration in a Nuxt application on GitHub.
Prerequisites
Steps
Having met the prerequisites, the steps are as follows:
- Set up the Cerbos policy repository
- Set up the Cerbos PDP
- Add the Cerbos client to your Nuxt application
- Create an API route
- Make permission checks across your Nuxt pages and components
Set up the Cerbos policy repository
A Cerbos policy repository is a collection of YAML files that define access control rules for your application. It's essential for specifying who can do what within your app. These policies dictate the actions different user roles can perform on various resources.
A resource is an application-specific concept that applies to anything that requires access rules. For example, a document is a resource that can be altered, viewed, deleted, etc. by different users depending on the access control rules. Read more about the best practices for structuring your policy repository in our documentation.
Your Cerbos policy repository can be stored on your disk, on git, or any S3-compatible storage system. To set up a Cerbos policy repository on the disk, within the Nuxt application, do the following:
- In your project's root, create a
cerbos
folder, then apolicies
sub-folder within it. - Within the
policies
folder, create a YAML file which will contain the rules for performing permission checks in your Nuxt application. For example, create adocuments.yaml
resource policy file. - Populate the
documents.yaml
file with rules for actions that can be performed on a document, check the example below. Learn more in Cerbos resource policies documentation.
---
apiVersion: api.cerbos.dev/v1
resourcePolicy:
version: default
resource: document
rules:
- actions: ['view', 'change', 'destroy']
effect: EFFECT_ALLOW
roles:
- admin
- actions: ['view', 'change']
effect: EFFECT_ALLOW
roles:
- user
condition:
match:
expr: request.resource.attr.author == request.principal.id
Now we’ve defined a simple resource policy file documents.yaml
which allows admin users to view
, change
, and destroy
any document
resource within the system. Non-admin users are allowed to view
and change
the document
resource if the condition is matched that the given user is also the document author.
Note that a separate policy file is expected for different types of resources and principals we want to create policies about. To showcase this, in the linked demo GitHub example there is a contacts.yaml
resource policy file alongside the documents.yaml
one.
Cerbos policy repository can be further enriched with defining context-aware roles, schemas, scopes, tests, and various other features explained in comprehensive Cerbos documentation.
Set up the Cerbos PDP
Cerbos PDP is the Policy Decision Point, a component that evaluates application requests against authZ policies to make access decisions; determining whether a user action on a resource is allowed.
In this demo, we’ll set a Cerbos PDP within your repository, as a separate module, using the previously created cerbos
directory. To run Cerbos PDP locally, do the following:
- Create a Cerbos PDP server configuration file within
cerbos
directory. You can name itconf.yaml
. - For simplest configuration, within the
conf.yaml
file define the port exposed for listening to HTTP (and/or gRPC) requests and the location of the Cerbos policy repository. The simplestconf.yaml
file would look like the one shown below:
---
server:
httpListenAddr: ":3592"
storage:
driver: "disk"
disk:
directory: /policies
For more robust configuration, make sure to check our Cerbos PDP configuration documentation.
Your file Cerbos-related file structure now might look like the following:
.
├── cerbos
│ └── policies
│ ├── documents.yaml
│ └── contacts.yaml
└── conf.yaml
Position your terminal within the cerbos
directory. If you have Docker installed, you can simply run the following command to start Cerbos PDP locally in a Docker container.
docker run --rm --name cerbos -t \
-v $(pwd)/policies:/policies \
-p 3592:3592 \
ghcr.io/cerbos/cerbos:latest server
--config=conf.yaml
Cerbos PDP runs as a separate process from your Nuxt application. Here, we ran it as a standalone service within a docker container, but this is not a requirement. Cerbos is designed to be adaptable to your infrastructure. So if you want to run Cerbos PDP as a service, a sidecar, or a lambda function, for instance, check the Cerbos deployment documentation to learn more about Cerbos deployment patterns.
Add the Cerbos client to your Nuxt application
Adding a Cerbos client is essential for simplifying the communication between your Nuxt application and the Cerbos PDP. The Client will allow you to make user permission checks from your Nuxt application in an elegant manner.
To add the Cerbos client to your Nuxt application, follow these steps:
- Select the Cerbos client you want to use.
- Choose between
@cerbos/http
for HTTP interactions or@cerbos/grpc
for gRPC in server-side applications.
- Choose between
- Install the chosen client package using the
npm install
command - In your Nuxt project, within the
utils
folder, create a utility filecerbos.ts
to instantiate the Cerbos client. - Export the instance for reuse across your Nuxt application.
The above mentioned cerbos.ts
file would look like this:
import { HTTP as Cerbos} from "@cerbos/http";
export const cerbos = new Cerbos("localhost:3592");
Create an API route
A Nuxt API route is a feature in Nuxt.js used to define server-side logic and handle HTTP requests within the Nuxt application. These routes allow developers to create various back-end functionalities in the Nuxt project, such as data fetching, form submissions, or in this case authorization.
To create an API route in Nuxt for Cerbos permission checks:
- Create an
isAllowed.ts
file within theserver/api
folder of your Nuxt application. - Define and export the event handler
- In
isAllowed.ts
file, usedefineEventHandler
fromnuxt-helpers
to export your API handling function. - Within this function, call the Cerbos
.isAllowed(...)
method to check user permissions based on the request's user and resource details.
- In
import { cerbos } from "../utils/cerbos";
// Pull the user info from the session in your Nuxt applications
const user = {
id: "000012345",
roles: ["user"]
}
export default defineEventHandler(async (event) => {
const query = getQuery(event)
const document = {
id: query.documentId as string
}
const requestBody = {
principal: user,
resource: { // Pull the resource info from the data storage in your Nuxt applications. Pass Resource ID within the event as a query param, like we did here.
kind: "document",
id: document.id,
attributes: {
author: "000012347"
}
},
action: "approve"
}
const isAllowed = await cerbos.isAllowed(requestBody)
.catch( (error)=> {
console.log( error );
return false;
})
})
That’s it! You can now universally call this API as /api/isAllowed
across your Nuxt application pages and components.
Make permission checks across your Nuxt pages and components
Let’s see the usage of Cerbos permission checks across your Nuxt application pages in action. Let’s say we’ve created a page for each of our documents on the path /documents/[id]
. To do that:
- Create a
documents
folder under thepages
folder of your application. - Within the
documents
folder, create an[id].vue
file.
Nuxt offers route validation via the validate
property in definePageMeta()
in each page you wish to validate. The validate
property accepts the route as an argument.
To use the /api/isAllowed
route defined in the previous step you can add the following snippet to the bottom of your recently created [id].vue
(or any other vue) file.
definePageMeta({
validate: async (route) => {
const { data: isAllowed } = await useFetch('/api/isAllowed',
{
headers: useRequestHeaders(),
query: { documentId: route.params.id }
})
return isAllowed.value;
}
})
It’s that simple!
To sum up
All you have to do to use Cerbos authorization in your Nuxt application is to:
- create Cerbos policies you will be using to make decisions over who should be able to do what within your application,
- run a Cerbos PDP which upon being called will be checking those policies,
- install the Cerbos client within your Nuxt application,
- create an API route to enable its usage across your Nuxt application,
- start invoking the exported API route to perform Cerbos
.isAllowed(...)
checks and determine whether your application user should be allowed to make a certain action on a certain resource.
Further steps
In this tutorial you saw how to add fine-grained access control with Cerbos to your Nuxt applications. If you liked it make sure to check out Cerbos Hub.
Cerbos Hub saves time managing and synchronizing every Cerbos PDP and policy repository across all your applications and services. It helps connect your Cerbos policy repository and your Cerbos PDP instances and manage them collaboratively and smoothly from a single place.
We also published a series of articles with step-by-step instructions on how to Get started with Cerbos Hub. Take a look if you’re interested in seeing how it works!
Posted on January 15, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.