# RBAC for Aerospike Graph Service

## Overview

This page describes how to set up Role Based Access Control (RBAC) for the Aerospike Graph Service (AGS) using [Java Web Tokens (JWTs)](https://jwt.io/introduction).

We recommend using RBAC on a secure network connection between client applications and AGS.

### Multi-tenant graph support

If your AGS instance uses [multi-tenant graphs](https://aerospike.com/docs/graph/manage/multi-tenant), you can create JWTs that assign different roles to different graphs by specifying a graph name in your role definition. See the [Create JWTs](#create-jwts) section of this page for details.

## Enable RBAC

Enable RBAC for your AGS instance with the following configuration options:

| Option | Required? | Value |
| --- | --- | --- |
| `aerospike.graph-service.auth.jwt.secret` | yes | Any string that you choose. |
| `aerospike.graph-service.auth.jwt.issuer` | yes | Your organization or a third-party authentication service. |
| `aerospike.graph-service.auth.jwt.algorithm` | no | One of: `HMAC256`, `HMAC384`, `HMAC512`. Default is `HMAC256`. |

::: note
For a complete list, see [Configuration options](https://aerospike.com/docs/graph/reference/config).
:::

After RBAC security is enabled, all connections with AGS must carry a Java Web Token (JWT) with the correct secret and issuer, and all users must have sufficient privileges to run their queries.

### Authentication details

-   When authentication is enabled, the `evaluationTimeout` parameter is ignored when it is part of Gremlin queries.
-   To use the `evaluationTimeout` parameter when authentication is enabled, set it globally with the [`aerospike.graph-service.evaluationTimeout`](https://aerospike.com/docs/graph/reference/config#aerospikegraph-serviceevaluationtimeout) option in your [properties file](https://aerospike.com/docs/graph/reference/config).

## Roles

Role access levels in AGS include:

-   [READ](#read)
-   [READ\_WRITE](#read_write)
-   [ADMIN](#admin)

### `READ`

Can read data. No write or admin privileges.

The following commands are blocked for `READ` users:

| Blocked Gremlin steps |
| --- |
| `addV` |
| `addE` |
| `drop` |
| `mergeE` |
| `mergeV` |
| `property` |

| Blocked call steps |
| --- |
| `aerospike.graph.admin.rbac-jwt.issue-token` |
| `aerospike.graph.admin.index.drop` |
| `aerospike.graph.admin.index.create` |
| `aerospike.graphloader.admin.bulk-load.*` (all `bulk-load` steps are blocked) |

### `READ_WRITE`

Can read data and perform write operations such as `addV()`, `addE()`, and `property()`.

All Gremlin steps are available to `READ_WRITE` users. The following commands are blocked:

| Blocked call steps |
| --- |
| `aerospike.graph.admin.rbac-jwt.issue-token` |
| `aerospike.graph.admin.index.drop` |
| `aerospike.graph.admin.index.create` |

### `ADMIN`

Can perform read and write operations, plus create and delete [indexes](https://aerospike.com/docs/graph/develop/query/indexing). No Gremlin steps or call steps are blocked.

## Create JWTs

Use the following procedure to create JWTs for use with graph authentication.

1.  Create the `ADMIN` JWT

An admin user first creates a token with admin-level privileges. The first admin token must be created using an external token authority.

[jwt.io](https://jwt.io) provides a free utility for generating JWTs.

-   Select an algorithm from the dropdown menu. Valid algorithms for use with AGS are:
    
    -   ‘HS256’ (corresponds to ‘HMAC256’)
    -   ‘HS384’ (corresponds to ‘HMAC384’)
    -   ‘HS512’ (corresponds to ‘HMAC512’)
    
    The `HEADER` field auto-populates based on your choice.
    
-   Fill in the `PAYLOAD` field with the following, edited to suit your needs.
    
    If your AGS instance does not use [multi-tenant graphs](https://aerospike.com/docs/graph/manage/multi-tenant), the `role` field contains only the specified role. If your AGS instance uses multi-tenant graphs, the `role` field may contain:
    
    -   A list of key-value pairs with the graph name and the role for that graph.
    -   A single role that applies to all graphs.
    
    The following example shows the `PAYLOAD` field for an AGS instance **without** multi-tenant graphs:
    
    Terminal window
    
    ```bash
    {
    
      "iss": "jwt.io",
    
      "iat": 1717107890,
    
      "exp": 14210121600,
    
      "aud": "",
    
      "sub": "admin",
    
      "role": "ADMIN"
    
    }
    ```
    
    The following example shows the `PAYLOAD` field for an AGS instance **with** graphs named `GraphA` and `GraphB`:
    
    Terminal window
    
    ```bash
    {
    
      "iss": "jwt.io",
    
      "iat": 1717107890,
    
      "exp": 14210121600,
    
      "aud": "",
    
      "sub": "admin",
    
      "role": {"GraphA" : "ADMIN", "GraphB" : "READ_WRITE"}
    
    }
    ```
    
-   Add your secret to the `VERIFY SIGNATURE` field, and the encoded token on the left side is ready to use.
    

The following diagram shows the procedure for creating a token with an external token issuer:

 ![Creating JWT with an external token issuer](https://aerospike.com/docs/_astro/creating-JWT-with-ext-seq.xoT8cKwU_Z2aq9uV.png)

2.  Create subsequent JWTs using admin token

The admin user can create tokens for other users, including admin tokens. Other users can use their tokens for graph queries, and the issuer and secret credentials are not required with the application code.

The following diagram shows the procedure for creating a token with the AGS `aerospike.graph.admin.rbac-jwt.issue-token` command:

 ![Creating JWT with AGS](https://aerospike.com/docs/_astro/creating-JWT-with-AGS-seq.DiQWVw1e_1aioqi.png)

3.  The admin user can create tokens with the Gremlin call step `aerospike.graph.admin.rbac-jwt.issue-token`. Provide the new token’s username and intended role as parameters:

```plaintext
g.call("aerospike.graph.admin.rbac-jwt.issue-token")

  .with("username", "<USERNAME>")

  .with("role", "<ROLE>")

  .next()
```

## Connect to AGS using a JWT

The following diagram shows the procedure for connecting to AGS with a JWT:

 ![Connecting to AGS with a JWT](https://aerospike.com/docs/_astro/connect-seq.ap3gZ6sI_1XOYJv.png)

### Using a JWT over a Gremlin server connection

The following Java code example demonstrates a Gremlin server login with a JWT:

```java
final Cluster cluster = Cluster.build()

         .addContactPoint("localhost").port(8182)

         .credentials(<USERNAME>, <TOKEN>)

         .create();
```

### Using a JWT over an HTTP connection

To authenticate an HTTP connection with a JWT, set the `Authorization` property to `Bearer <JWT>`, where `<JWT`\> is a base64 encoded string of a JWT.

The following Java code example demonstrates setting up an HTTP connection with a JWT:

```java
public String adminIndexListHeaders(final String userCredentials) {

        try {

            final URL url = new URL("http://localhost:9090/admin/index/list");

            final HttpURLConnection con = (HttpURLConnection) url.openConnection();

            // Send request to the server and read reply

            final String token = "Bearer " + new String(Base64.getEncoder().encode(userCredentials.getBytes()));

            // Send request to the server and read reply

            con.setRequestMethod("GET");

            con.setRequestProperty("Authorization", token);

            // Read input stream into String

            final byte[] bytes = con.getInputStream().readAllBytes();

            final String response = new String(bytes);

            return response;

        } catch (final Exception e) {

            throw new RuntimeException(e);

        }

    }
```