> ## Documentation Index
> Fetch the complete documentation index at: https://docs.formal.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Identities

> Manage users and groups

## Overview

This page covers how to create and manage identities in Formal.

There are two types of identities in Formal:

* **Users**: Individual human or machine identities
* **Groups**: Collections of users for streamlined permission management

<Note>
  **Native Users are not identities**: Native users are a separate concept from identities.
  While identities (users and groups) represent who is accessing resources through Formal, native users hold
  the credentials Connectors use to authenticate to the underlying resources (databases, servers, etc.).
  To learn more about native users, refer to [our Native Users documentation](/docs/guides/core-concepts/resources/native_users).
</Note>

## Users

Users represent identities that connect to resources through Formal Connectors. Every query, command, or API call can be attributed to a specific user for auditing and policy enforcement.

### User Types

<Tabs>
  <Tab title="Human Users">
    **Human Users** are for employees who need direct access to protected resources.
    They can be invited manually but often organizations provision those users via SCIM or SSO (Formal supports JIT provisioning via SSO).
    They can then retrieve their username and access token from the Formal console to connect through Connectors.
    **Use cases:**

    * Engineers querying production databases
    * Analysts accessing data warehouses
    * DevOps teams managing infrastructure via SSH
  </Tab>

  <Tab title="Machine Users">
    **Machine Users** are for applications, BI tools, and automated systems that
    connect to resources. Unlike human users, machine users don't receive email
    invitations and can have longer-lived credentials.
    **Use cases:**

    * Internal applications querying databases
    * BI tools like Looker, Metabase, Tableau
    * CI/CD pipelines accessing infrastructure
    * ETL jobs moving data
    * AI code agents
  </Tab>
</Tabs>

### Creating Users

<Steps>
  <Step title="Navigate to Users">
    Go to [Users](https://app.formal.ai/users) in the Formal console
  </Step>

  <Step title="Click New User">Select **New User** button</Step>
  <Step title="Select Identity Type">Choose **Human** or **Machine**</Step>

  <Step title="Provide user information">
    * **Name**: Full name or application name - **Email**: For human users
      (receives credentials) - **Temporary**: (Optional) Set expiration time for
      temporary access - **Groups**: (Optional) Add to groups
  </Step>
</Steps>

<Tip>
  Temporary users are automatically deleted after the specified time—perfect for
  contractors or time-limited access grants.
</Tip>

### Access Tokens

Formal decouples credentials from underlying resources, enabling each user to have their own set of short-lived, rotating credentials.

#### Default Validity Period

**7 days** - Access tokens automatically expire and must be refreshed.

#### Configuring Token Validity

To adjust the validity period for your organization, contact Formal support. Organization administrators are authorized to make this request.

### Accessing Formal Credentials

<Tabs>
  <Tab title="Web Console">
    1. Navigate to [the Formal console](https://app.formal.ai)
    2. Click the **Access Token** button in the bottom right corner
    3. Copy your credentials (username and access token)

    <img src="https://mintcdn.com/formal/e2sZZJeIjJomo9ox/assets/images/credentials.png?fit=max&auto=format&n=e2sZZJeIjJomo9ox&q=85&s=0558a52dd79f3b9f73d07eed1e5564ba" alt="Access credentials in console" width="3456" height="1914" data-path="assets/images/credentials.png" />
  </Tab>

  <Tab title="Desktop App">
    ```bash theme={null}
    formal auth credentials 
    ```

    This displays your Formal username and
    access token for connecting through Connectors.
  </Tab>
</Tabs>

#### Passing Formal Credentials

Connect to resources using your Formal credentials:

```bash theme={null}
# PostgreSQL example
psql -h connector.joinformal.com -p 5432 \
  -U "idp:formal:human:alice@example.com" \
  -d production_db

# Password: <your access token from console>
```

#### Using Hashed Access Tokens

Some database clients have limitations with password length. For example, the standard `mysql` and `mariadb` CLI clients don't support passwords longer than 80 characters when using the `-p` (interactive password) option. Since Formal access tokens typically exceed this limit, you'll need to use hashed tokens instead.

**What are hashed tokens?**

Hashed tokens are shortened versions of your full access tokens that are compatible with clients that have password length restrictions. They maintain the same security properties while working within these constraints.

**How to obtain a hashed token:**

1. Navigate to [the Formal console](https://app.formal.ai)
2. Click the **Access Token** button in the bottom right corner
3. Click on **Hashed Access Token** to view your hashed token
4. Copy the hashed token for use with restricted clients

**When to use hashed tokens:**

* MySQL/MariaDB CLI clients with the `-p` flag
* Other database clients that limit password length
* Legacy applications with password field restrictions

<Warning>
  Hashed tokens have the same access level as your full access token. Treat them with the same security precautions and never share them.
</Warning>

### Using End User Identities

There may be times when a machine identity interacting with the Connector is itself making requests on behalf of *end users*. For example, you may
want to control access to a Retool dashboard. Various technologies support the notion of *end user identities* where the machine user can map a request
to a separate Formal user identity. For more information on how to specify the end user, refer to the resource page for that particular technology.

<Note>
  End user identities do not require the machine identity to have access to the end user identity's access token. As a result,
  when looking at end user identities, the machine identity needs to be trusted when writing policies against end users.
</Note>

**External IDs** solve this by mapping end-user identities from external systems to Formal users:

<Steps>
  <Step title="Add External ID to Human User">
    Map the user's ID in your BI tool (e.g., Looker user ID 12345) to their
    Formal user
  </Step>

  <Step title="Configure your application">
    Update your application to propagate the end-user ID when connecting through
    Formal. Formal provides SDKs to simplify this:

    * [formal-sqlcommenter for Python/Django](https://pypi.org/project/formal-sqlcommenter/)
    * Built-in integrations for Metabase, Looker, and more
  </Step>

  <Step title="Verify attribution">
    Check [Logs](/docs/guides/observability/logs) to confirm queries are
    attributed to the correct end user
  </Step>
</Steps>

This enables accurate auditing and per-user policy enforcement even when using shared application credentials.

## Groups

Groups allow you to apply policies and native user assignments to multiple users simultaneously, streamlining permission management.

<CardGroup cols={2}>
  <Card title="Simplify Policy Management" icon="shield-halved">
    Write policies once for a group instead of per-user
  </Card>

  <Card title="Consistent Access" icon="users-gear">
    Ensure all group members have the same permissions
  </Card>

  <Card title="Native User Mapping" icon="key">
    Assign database credentials at the group level
  </Card>

  <Card title="Flexible Membership" icon="user-plus">
    Users can belong to multiple groups
  </Card>
</CardGroup>

### Creating Groups

<Steps>
  <Step title="Navigate to Groups">
    Go to [Groups](https://app.formal.ai/groups) in the Formal console
  </Step>

  <Step title="Click New Group">Create a new group</Step>

  <Step title="Name the group">
    Choose a descriptive name (e.g., "Engineering Team", "Analytics", "External
    Contractors")
  </Step>

  <Step title="Add members">Select users to add to the group</Step>
</Steps>

### Managing Group Membership

<Steps>
  <Step title="Open group details">Click on a group in the Groups list</Step>

  <Step title="Add or remove users">
    Select users from the dropdown to add them, or remove existing members
  </Step>
</Steps>

<Note>
  A user can be part of multiple groups. Their effective permissions are the
  union of all group policies plus any user-specific policies.
</Note>

## Best Practices

<AccordionGroup>
  <Accordion title="Use Groups for Team-Based Access" icon="users">
    Create groups that match your organizational structure (teams, departments,
    roles). This makes policy management scalable as your organization grows.
  </Accordion>

  <Accordion title="Leverage Temporary Users for Contractors" icon="clock">
    Set expiration dates for external contractors or time-limited access needs.
    Formal automatically cleans up expired users.
  </Accordion>

  <Accordion title="Implement External IDs for BI Tools" icon="chart-line">
    Ensure end-user accountability even when using shared application credentials.
    This is critical for compliance and security auditing.
  </Accordion>

  <Accordion title="Use Machine Users for Applications" icon="robot">
    Never share human user credentials with applications. Create dedicated machine
    users for each application or service.
  </Accordion>

  <Accordion title="Minimize Direct User Assignments" icon="user-minus">
    Prefer group-based native user assignments over individual assignments. This
    reduces configuration complexity.
  </Accordion>
</AccordionGroup>

## Configuration

<Tabs>
  <Tab title="Web Console">
    Manage users and groups through the Formal console at:

    * [Users](https://app.formal.ai/users)
    * [Groups](https://app.formal.ai/groups)
  </Tab>

  <Tab title="Terraform">
    ```hcl theme={null}
    # Create users
    resource "formal_user" "alice" {
      name  = "Alice Smith"
      email = "alice@example.com"
      type  = "human"
    }

    resource "formal_user" "bi_tool" {
      name = "Looker Application"
      type = "machine"
    }

    # Create groups
    resource "formal_group" "engineering" {
      name = "Engineering Team"
    }

    # Add users to groups
    resource "formal_group_user_link" "alice_eng" {
      group_id = formal_group.engineering.id
      user_id  = formal_user.alice.id
    }
    ```
  </Tab>
</Tabs>

## Understanding Identities in Logs

Individual logs will specify which identity was used. If a formal identity was used,
the resulting `user` field will have `user.type` equal to `formal`. In addition,
`user.formal` will be populated with the identity. `user.formal.type` will specify whether the identity will be `human` or `machine`.

If a Formal identity is not specified, `user.formal` will be empty and `user.type` will be `native`.

## Next Steps

<CardGroup cols={2}>
  <Card title="Assign Native Users" icon="key" href="/docs/guides/core-concepts/resources#native-users">
    Map Formal users to resource credentials
  </Card>

  <Card title="Write Policies" icon="shield-check" href="/docs/guides/policies/introduction">
    Control access based on users and groups
  </Card>

  <Card title="Configure External IDs" icon="link" href="#external-ids-and-identity-propagation">
    Enable end-user attribution for BI tools
  </Card>

  <Card title="Monitor Sessions" icon="signal-stream" href="/docs/guides/observability/sessions">
    See what users are accessing in real-time
  </Card>
</CardGroup>
