# App roles, users, and access tokens

> Give your application custom business roles and let its backend manage app users through a scoped bearer token.

Source: https://docs.stacksync.com/enterprise-os/applications/roles-and-app-tokens

A finance app may need Accountants and Approvers, while a customer portal needs Customers and Support agents. These permissions belong to your application. EOS authenticates the person, stores their app membership and role, and returns that identity so your backend can enforce the right permissions.

## Separate app roles from EOS resource roles

| Field               | What it controls                             | Examples                                |
| ------------------- | -------------------------------------------- | --------------------------------------- |
| `eos_resource_role` | EOS infrastructure and resource management   | `owner`, `editor`, `viewer`, `operator` |
| `app_role`          | Business permissions implemented by your app | `accountant`, `approver`, `customer`    |

An app member without an EOS resource grant receives `eos_resource_role: "operator"`. Adding an app user does not make them a member of your workspace or give them access to deployment settings, source code, or credentials. An app role called `admin` has no EOS administration privileges.

Each app starts with **Admin** (`admin`), **Editor** (`editor`), and **Viewer** (`viewer`) roles. Existing apps receive these defaults too. They are editable and deletable, and deleted defaults are not recreated during redeployment. No user is automatically assigned an app role. A role can be deleted only after you clear or change its assignments, including pending invitations.

Each role has a name, an ID unique within the app, and an informative description. IDs start with a lowercase letter and contain up to 64 lowercase letters, digits, underscores, or hyphens. The ID is immutable; update the name or description, or create a replacement role and move its users. Your application defines what each role permits.

## Manage roles and users in the dashboard

1. Open **Applications → your application → Users and Access** as an app Owner.
2. Use **App roles → Add app role** to create a role. You can also create one from a user's **App role** dropdown.
3. Use **Add Users** for EOS resource sharing, or **Add app user** for application membership.
4. Assign the business role in **App role**. Use **No app role** to clear the assignment.

The App roles, Users, and Groups tables each have a search field. Search matches text across each row's fields. The tables distinguish an empty list from a search with no matches. Pending workspace invitees receive their assigned app role only after accepting their invitation.

App membership is independent of EOS resource grants. Removing an app member clears that membership and app role; an independent resource grant or a broader runtime policy can still allow the person to open the app. For an app limited to explicitly admitted people, choose **Specific members** in [managed authentication](/enterprise-os/applications/managed-authentication).

<div data-with-frame="true">
  <figure><img src="/images/enterprise-os/app-roles-and-users.png" alt="The EOS Users and Access tab shows default Admin, Editor, and Viewer app roles, independent EOS resource and app role columns, and searchable tables." width="1600" height="1310" loading="lazy" decoding="async" /><figcaption>Keep application roles separate from EOS resource permissions in Users and Access.</figcaption></figure>
</div>

## Automate with EOS CLI 5.2.0

Run `eos update`, sign in, and select the workspace. These commands require app Owner access and accept an app ID or project name:

```sh
eos app roles list finance-portal --json
eos app roles create finance-portal accountant --name Accountant --description 'Reviews accounts and prepares reports'
eos app roles update finance-portal accountant --name Accountant --description 'Reviews accounts, prepares reports, and exports statements'
eos app users set finance-portal person@example.com --role accountant
eos app users list finance-portal --json
```

Setting a user without `--role` clears their app role while keeping membership. Use the returned numeric user ID when removing membership:

```sh
eos app users set finance-portal USER_ID
eos app users remove finance-portal USER_ID
eos app roles delete finance-portal accountant
```

## Give your backend its own access token

An app access token identifies **the application**, not a visiting user. Use it when your backend needs to add users, assign roles, or create custom roles in its own app.

Create a token in **Applications → your application → App access tokens → Create access token**. The token table includes search, creation dates, and revocation status. Or create one through the CLI:

```sh
eos app tokens create finance-portal backend --token-file /private/finance-portal-token
eos app tokens list finance-portal --json
```

The token secret is returned only at creation. `--token-file` creates a new private file with mode `0600` on POSIX systems and refuses to overwrite an existing file. Without that flag, creation output includes the secret.

Store the token in a server-side deployment variable such as `EOS_APP_ACCESS_TOKEN`. Never include it in a frontend bundle, a public environment variable, a URL, or source control. The app must authorize its own user before using this credential to change roles or memberships.

Multiple tokens can be active for the same app. To rotate, create a replacement, deploy it, verify your backend's calls, then revoke the old token:

```sh
eos app tokens revoke finance-portal TOKEN_ID
```

Revocation affects subsequent requests. App access tokens cannot create other tokens, change EOS resource roles, manage workspace members, administer deployments, or access another app.

## Manage users and roles through the app API

Send the app access token as `Authorization: Bearer ...` to the EOS API. These endpoints derive the app from the token; no workspace or app ID is required in the URL or body.

| Method and path                            | Behavior                                                                    |
| ------------------------------------------ | --------------------------------------------------------------------------- |
| `GET /api/app-access/v1/roles`             | List the app's roles.                                                       |
| `POST /api/app-access/v1/roles`            | Create a role with `id`, `name`, and optional `description`.                |
| `PUT /api/app-access/v1/roles/{roleId}`    | Update the role's `name` and `description`.                                 |
| `DELETE /api/app-access/v1/roles/{roleId}` | Delete an unassigned role.                                                  |
| `GET /api/app-access/v1/users`             | List explicit app members and their role assignments.                       |
| `PUT /api/app-access/v1/users`             | Add or update a member using `email` or a known `user_id`, plus `app_role`. |
| `DELETE /api/app-access/v1/users/{userId}` | Remove app membership and the app role.                                     |

For example, from server-side JavaScript:

```js
const response = await fetch(
  'https://enterprise-os.stacksync.ai/api/app-access/v1/users',
  {
    method: 'PUT',
    headers: {
      Authorization: `Bearer ${process.env.EOS_APP_ACCESS_TOKEN}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      email: 'person@example.com',
      app_role: 'accountant',
    }),
  },
);
if (!response.ok) throw new Error(`EOS membership update failed: ${response.status}`);
const { user } = await response.json();
```

Add a new person by email. They authenticate through EOS; adding membership does not sign them in or send an invitation automatically. A user ID can address only someone already visible in the app or workspace. Pass `app_role: null` to clear an assignment. Disabled users cannot be added. App collaboration requires a claimed workspace.

Owner-authenticated management clients can use `/workspace/{workspace_id}/api/access/apps/{app_id}/app-roles`, `/app-members`, and `/app-tokens` instead. These routes use the owner's EOS management credential and permissions. See the [EOS OpenAPI document](https://enterprise-os.stacksync.ai/openapi.json) for request details.

Read [the verified identity contract](/enterprise-os/applications/managed-authentication#read-the-current-user) to use these assignments in your application.