Authentication

How to authenticate with Membrane

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 page in Console Settings.

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" }
)
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"
)
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>"))
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')
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();
$token = JWT::encode([
    'workspaceKey' => '<WORKSPACE_KEY>',
    'tenantKey' => '{TENANT_ID}',
    'name' => '{TENANT_NAME}',
    'exp' => time() + 7200,
], '<WORKSPACE_SECRET>', 'HS256');

Token fields

FieldRequiredDescription
workspaceKeyYesYour workspace key
tenantKeyNoIdentifier of the tenant (user, team, or org). Omit for workspace-level operations.
nameNoHuman-readable tenant name (helps with troubleshooting)
fieldsNoAdditional 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 page in Console Settings.

Long-lived Tokens

For tokens that don't expire, create a Long-lived Token on the 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:

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.

Membrane Instance Token

For self-hosted Membrane instances. See Self-hosting for details.