# Jitsi Meet JWT authentication

> Set ENABLE_AUTH=1, AUTH_TYPE=jwt, JWT_APP_ID and JWT_APP_SECRET in the Docker .env, restart, then sign HS256 tokens whose iss and aud are your app ID, sub is your Jitsi domain, room is the room name (or *), and exp is in the future. Users join with https://meet.example.com/Room?jwt=TOKEN.

Source: https://jitsi.help/guides/jitsi-jwt-authentication/
Updated: September 26, 2026
Publisher: Jitsi Help (https://jitsi.help/)

JWT authentication turns Jitsi Meet from "anyone who guesses the URL can join" into "only people your application approves can join". Your backend signs a short-lived token for each user, and Jitsi checks it before letting them in. It is the standard way to embed Jitsi into a product, a course platform or a telehealth app.

This guide matches the configuration our platform enables for customers on `stable-11031`.

## How it works

1. Your app decides a user may join room `team-standup`.
2. Your server signs a token with the shared secret.
3. The user opens `https://meet.example.com/team-standup?jwt=<token>`.
4. Prosody validates the signature, expiry, issuer, audience, domain and room, then admits the user.

## 1. Enable JWT in Docker

In `.env`:

```ini
ENABLE_AUTH=1
AUTH_TYPE=jwt
JWT_APP_ID=my_app
JWT_APP_SECRET=use-a-long-random-secret
JWT_ACCEPTED_ISSUERS=my_app
JWT_ACCEPTED_AUDIENCES=my_app
# 1 lets people without a token join rooms that already exist.
ENABLE_GUESTS=1
```

Generate the secret with something like `openssl rand -hex 32`. Then recreate the containers so Prosody picks up the new auth settings:

```bash
docker compose up -d --force-recreate
```

## 2. The token format

Header: `{"alg": "HS256", "typ": "JWT"}`

Payload:

```json
{
  "iss": "my_app",
  "aud": "my_app",
  "sub": "meet.example.com",
  "room": "team-standup",
  "exp": 1790000000,
  "context": {
    "user": {
      "id": "user-42",
      "name": "Priya Sharma",
      "email": "priya@example.com",
      "avatar": "https://example.com/avatars/42.png",
      "moderator": true
    }
  }
}
```

| Claim | Must be | Notes |
|---|---|---|
| `iss` | Your `JWT_APP_ID` | Checked against `JWT_ACCEPTED_ISSUERS` |
| `aud` | Your `JWT_APP_ID` | Checked against `JWT_ACCEPTED_AUDIENCES` |
| `sub` | Your Jitsi domain | The public hostname, not the internal `meet.jitsi` |
| `room` | Room name or `*` | Lowercase room names avoid case mismatches |
| `exp` | Future Unix time | Keep it short, for example one hour |
| `context.user` | Display details | `name` pre-fills the display name |

## 3. Sign tokens in your backend

### Node.js

```js
import jwt from "jsonwebtoken";

export function jitsiToken({ room, user, moderator }) {
  return jwt.sign(
    {
      iss: process.env.JWT_APP_ID,
      aud: process.env.JWT_APP_ID,
      sub: "meet.example.com",
      room,
      context: { user: { id: user.id, name: user.name, email: user.email, moderator } },
    },
    process.env.JWT_APP_SECRET,
    { algorithm: "HS256", expiresIn: "1h" },
  );
}
```

### Python

```python
from datetime import datetime, timedelta, timezone
import jwt  # PyJWT

def jitsi_token(room: str, user: dict, moderator: bool) -> str:
    payload = {
        "iss": APP_ID,
        "aud": APP_ID,
        "sub": "meet.example.com",
        "room": room,
        "exp": datetime.now(timezone.utc) + timedelta(hours=1),
        "context": {"user": {"id": user["id"], "name": user["name"], "moderator": moderator}},
    }
    return jwt.encode(payload, APP_SECRET, algorithm="HS256")
```

Then send the user to `https://meet.example.com/{room}?jwt={token}`, or pass the token to the IFrame API as the `jwt` option.

## 4. Moderators and guests

With JWT enabled, token holders are authenticated users and can start rooms. With `ENABLE_GUESTS=1`, people without a token can join a room after it has started, as guests.

Recent releases read `context.user.moderator` to decide who gets moderator rights. Whether that flag is enforced depends on the Prosody modules active on your server, so test with two browsers: one host token with `moderator: true` and one guest token with `false`. If both end up as moderators, your release is promoting every authenticated user, and you need the token affiliation module or a newer release.

## 5. Embed with the IFrame API

```html
<script src="https://meet.example.com/external_api.js"></script>
<div id="meet" style="height: 600px"></div>
<script>
  const api = new JitsiMeetExternalAPI("meet.example.com", {
    roomName: "team-standup",
    jwt: TOKEN_FROM_YOUR_SERVER,
    parentNode: document.getElementById("meet"),
  });
</script>
```

## Common mistakes

- **`sub` set to the internal domain.** Use the public hostname users type.
- **Clock skew.** If the server clock is behind, fresh tokens look not-yet-valid. Keep NTP running.
- **Tokens signed in the browser.** The secret leaks with the page source.
- **Room case.** `Standup` in the URL and `standup` in the token can mismatch. Use lowercase everywhere.

Full error list: [Jitsi JWT not working](/troubleshooting/jitsi-jwt-not-working/).

## Want it done for you?

Our platform enables JWT per server and gives you a test token and host links from the dashboard, and our team integrates Jitsi JWT into existing apps as a [service](/services/jitsi-integration/).

## Frequently asked questions

### What claims does a Jitsi JWT need?

iss and aud set to your JWT_APP_ID, sub set to your Jitsi domain (for example meet.example.com), room set to the room name or * for any room, and exp as a Unix timestamp in the future. User details go under context.user.

### Can guests join without a token?

Yes, if ENABLE_GUESTS=1. Token holders create and moderate rooms, and people without a token can join a room once it exists. Set ENABLE_GUESTS=0 to require a token for everyone.

### Which algorithm does Jitsi use for JWT?

HS256 with a shared secret (JWT_APP_SECRET) is the common setup and what we use. RS256 with public keys is also supported for larger integrations where the signing key must stay on another system.

### Is the JWT secret safe in the browser?

No. Always sign tokens on your server and send only the finished token to the browser. Anyone who has the secret can mint tokens for any room.


---

Jitsi Help is an independent service. It is not affiliated with, endorsed by or sponsored by 8x8, Inc. or the Jitsi project. Jitsi and Jitsi Meet are trademarks of 8x8, Inc., used here only to describe the software we host and support.
