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

# Authentication

To use Membrane, you need a Membrane Token. This page explains the different types of tokens and how to get them.

## Membrane Token

The main way to authenticate. Sign a JWT with your workspace key and secret.

You can find your workspace key and secret on the [Access](https://console.getmembrane.com/w/0/settings/access) page in Console Settings.

```javascript theme={null}
import jwt from 'jsonwebtoken'

const token = jwt.sign(
  {
    workspaceKey: '<WORKSPACE_KEY>',
    tenantKey: '{TENANT_ID}', // Identifier of tenant (user, team, or org)
    name: '{TENANT_NAME}', // Human-readable name
  },
  '<WORKSPACE_SECRET>',
  { expiresIn: 7200, algorithm: 'HS512' },
)
```

```python theme={null}
import datetime, jwt

token = jwt.encode(
    {
      "workspaceKey": "<WORKSPACE_KEY>",
      "tenantKey": "{TENANT_ID}",
      "name": "{TENANT_NAME}",
      "exp": datetime.datetime.now() + datetime.timedelta(seconds=7200)
    },
    "<WORKSPACE_SECRET>",
    algorithm="HS256"
)
```

```go theme={null}
import (
    "time"
    "github.com/golang-jwt/jwt/v5"
)

claims := jwt.MapClaims{
    "workspaceKey": "<WORKSPACE_KEY>",
    "tenantKey":    "{TENANT_ID}",
    "name":         "{TENANT_NAME}",
    "exp":          time.Now().Add(time.Hour * 2).Unix(),
}

token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, _ := token.SignedString([]byte("<WORKSPACE_SECRET>"))
```

```ruby theme={null}
require 'jwt'

payload = {
  workspaceKey: '<WORKSPACE_KEY>',
  tenantKey: '{TENANT_ID}',
  name: '{TENANT_NAME}',
  exp: Time.now.to_i + 7200,
}

token = JWT.encode(payload, '<WORKSPACE_SECRET>', 'HS256')
```

```java theme={null}
String token = Jwts.builder()
    .claim("workspaceKey", "<WORKSPACE_KEY>")
    .claim("tenantKey", "{TENANT_ID}")
    .claim("name", "{TENANT_NAME}")
    .setExpiration(Date.from(Instant.now().plusSeconds(7200)))
    .signWith(new SecretKeySpec("<WORKSPACE_SECRET>".getBytes(), "HmacSHA256"), SignatureAlgorithm.HS256)
    .compact();
```

```php theme={null}
$token = JWT::encode([
    'workspaceKey' => '<WORKSPACE_KEY>',
    'tenantKey' => '{TENANT_ID}',
    'name' => '{TENANT_NAME}',
    'exp' => time() + 7200,
], '<WORKSPACE_SECRET>', 'HS256');
```

### Token fields

| Field          | Required | Description                                                                         |
| -------------- | -------- | ----------------------------------------------------------------------------------- |
| `workspaceKey` | Yes      | Your workspace key                                                                  |
| `tenantKey`    | No       | Identifier of the tenant (user, team, or org). Omit for workspace-level operations. |
| `name`         | No       | Human-readable tenant name (helps with troubleshooting)                             |
| `fields`       | No       | Additional metadata to store about the tenant                                       |

### Public/Private Key Signing

For stronger security, you can sign tokens with a public/private key pair instead of a shared secret. Pass the private key to the sign method and provide the public key in the workspace settings.

Use any asymmetric algorithm: `ES256`, `RS256`, `PS256`, etc.

### Test Token

For quick testing, get a pre-generated test token from the [Access](https://console.getmembrane.com/w/0/settings/access) page in Console Settings.

### Long-lived Tokens

For tokens that don't expire, create a Long-lived Token on the [Access](https://console.getmembrane.com/w/0/settings/access) page in Console Settings under the Client Tokens section.

## Workspace Management Token

For administrative operations that affect the entire workspace — managing tenants, updating workspace settings, importing/exporting configuration, and other operations that aren't scoped to a single tenant.

Include `isAdmin: true` in the token payload and omit `tenantKey`:

```javascript theme={null}
const adminToken = jwt.sign(
  {
    workspaceKey: '<WORKSPACE_KEY>',
    isAdmin: true,
  },
  '<WORKSPACE_SECRET>',
  { expiresIn: 7200, algorithm: 'HS512' },
)
```

## Developer Token

Acts on behalf of your Membrane account — can do anything you can across all your workspaces. Get one from API Tokens in [Console Settings](https://console.getmembrane.com/w/0/settings).

## Membrane Instance Token

For self-hosted Membrane instances. See [Self-hosting](/docs/managing-membrane/self-hosting) for details.
