# Authorization

Novel uses the CASL library to provide authorization checks for all the routes and actions you need for your SaaS.

{% embed url="<https://casl.js.org/v6/en>" %}

{% hint style="info" %}
**Important**

It is important to remember that authorization is an intentional exercise and not automatic. You need to put these checks in place where they are needed.
{% endhint %}

## Configuration

In `/config/auth.js` there is a roles object that you can modify to add role IDs and permission keys to.

{% code title="config/auth.js" lineNumbers="true" %}

```typescript
/**
 * These are roles within the app that can be assigned to users.
 *
 * They have permissions that can be applied per route. Additional permission checks can be added
 * per transaction via casl/ability.
 *
 * Make sure you update app/(app)/organization/team/members.tsx if you modify this.
 */
roles: {
	superuser: ['all', 'admin'],
	admin: ['read', 'write', 'delete'],
	user: ['read', 'write'],
},
```

{% endcode %}

You can add as many roles you need here, and as many permissions applied to the role here.

These are then auto-loaded during start up time and applied to a global authorizer and a session based authorizer.

{% embed url="<https://docs.novel.dev/guides/knowledge-base/novel-server/configure-roles-and-permissions>" %}

## Permission

The `Permission` object is a class that you can use to organize permissions in your application.

{% code title="feature.ts" lineNumbers="true" %}

```typescript
const permit = new Permission(anyActorWithAnId);

permit.allow('read', Post);
permit.deny('delete', Post);

await permit.persist();

// or fetch a stored permission
const permit = await Permission.fetch(anActorWithAnId);
```

{% endcode %}

### `new Permission(ObjectWithId)`

This creates a new Permission object that can be serialized later on. You can use this to temporarily create permissions in your feature code.

You can persist the permissions to database using `.persist()` below.

### `permit.allow(action: String, subject: String | ObjectWithId)`

This defines what you can use in the Permission object using the CASL Ability `.can` or `.cannot`. The signature for this is the same.

{% embed url="<https://docs.novel.dev/novel-server/routing/request-helpers#await-request.can-action-string-subject-any-fields-string>" %}

### `permit.deny(action: String, subject: String | ObjectWithId)`

This is the opposite of allow you can use in the Permission object using the CASL Ability `.can` or `.cannot`. The signature for this is the same.

{% embed url="<https://docs.novel.dev/novel-server/routing/request-helpers#await-request.cannot-action-string-subject-any-fields-string>" %}

### `permit.build(): Ability`

This is an internal abstraction to CASL's Ability.build function. This makes it so that you can perform CASL functions against the Permission Object

{% code title="feature.ts" lineNumbers="true" %}

```typescript
const permit = new Permission(anyActorWithAnId);

permit.allow('read', Post);
permit.deny('delete', Post);

const permissions = permit.build();

permission.can('read', Post); // returns true
```

{% endcode %}

### `await permit.persist()`

This persists the permissions defined during the lifecycle of the Permission object. It generates a serialized permission records, one row per action/scope into the `access_control` table.

### `await Permission.fetch(actor: String | ObjectWithId)`&#x20;

This is similar to `new Permission(ObjectWithId)`  but for an actor that has been persisted.

{% code title="feature.ts" lineNumbers="true" %}

```typescript
const permissions = await Permission.fetch(anyActorWithAnId);

permission.can('read', Post); // returns true
```

{% endcode %}

## Using with an API

It is important to be familiar with both authorization modes of Novel API. Discussed below:

{% embed url="<https://docs.novel.dev/novel-server/routing#protecting-routes>" %}

Combine the above with the request helpers associated with `permit.allow`and `permit.deny`.

{% embed url="<https://docs.novel.dev/guides/knowledge-base/novel-server/securing-an-endpoint>" %}

## Changelog

* 2024-12-20 - Initial Documentation


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.novel.dev/novel-server/authorization.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
