Nuxt authorization: How to implement fine-grained access control

kiselitza

aldin

Posted on January 15, 2024

Nuxt authorization: How to implement fine-grained access control

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

  • A working Nuxt web application
  • Docker installed in your working environment

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 a policies 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 a documents.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
Enter fullscreen mode Exit fullscreen mode

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 it conf.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 simplest conf.yaml file would look like the one shown below:
---
server:
  httpListenAddr: ":3592"
storage:
  driver: "disk"
  disk:
    directory: /policies
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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.
  • Install the chosen client package using the npm install command
  • In your Nuxt project, within the utils folder, create a utility file cerbos.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");
Enter fullscreen mode Exit fullscreen mode

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 the server/api folder of your Nuxt application.
  • Define and export the event handler
    • In isAllowed.ts file, use defineEventHandler from nuxt-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.
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;
    })
})
Enter fullscreen mode Exit fullscreen mode

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 the pages 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;
  }
})

Enter fullscreen mode Exit fullscreen mode

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!

💖 💪 🙅 🚩
kiselitza
aldin

Posted on January 15, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related