# Jitsi JWT authentication not working

> Decode the token and compare it with the server: iss and aud must equal JWT_APP_ID (or be in the accepted lists), sub must be the public Jitsi domain, room must match the room in the URL or be *, exp must be in the future on the server's clock, and the signature must use the same JWT_APP_SECRET. After changing auth settings, recreate the containers.

Source: https://jitsi.help/troubleshooting/jitsi-jwt-not-working/
Updated: September 26, 2026
Publisher: Jitsi Help (https://jitsi.help/)

JWT failures almost always come down to one claim not matching one setting. Decode the token (the middle part is base64url JSON) and check each row:

| Claim | Must match | Typical mistake |
|---|---|---|
| `iss` | `JWT_APP_ID` / `JWT_ACCEPTED_ISSUERS` | A different string in dev and prod |
| `aud` | `JWT_APP_ID` / `JWT_ACCEPTED_AUDIENCES` | Set to `jitsi` from an old tutorial |
| `sub` | The public domain, e.g. `meet.example.com` | Using the internal `meet.jitsi` |
| `room` | The room in the URL, or `*` | Case differs, or URL-encoded characters |
| `exp` | Later than the server's current time | Seconds vs milliseconds, clock skew |
| signature | Signed with `JWT_APP_SECRET`, HS256 | Secret has a trailing newline or space |

## The token is ignored and a login dialog appears

- The server is not in JWT mode. Check `.env` has `ENABLE_AUTH=1` and `AUTH_TYPE=jwt`, then **recreate** (not just restart) the containers: `docker compose up -d --force-recreate`.
- The token is not in the URL. It must be `?jwt=<token>` on the room URL, or the `jwt` option in the IFrame API.

## "Not allowed" or immediate disconnect

One of the claims in the table is wrong. The Prosody log names it:

```bash
docker compose logs --tail 100 prosody | grep -i token
```

## Tokens work for a while, then fail

- `exp` is too short, or set in milliseconds (a date far in the future is suspicious, a date in 1970 is milliseconds divided wrongly).
- The server clock drifts. Check `timedatectl` and keep NTP enabled.

## Works for one room, not others

The token's `room` is a specific name. Use `*` for any room, or mint one token per room. Keep room names lowercase in both the URL and the token.

## Guests cannot join, or can join without a token

That is `ENABLE_GUESTS`. `1` lets people without a token join rooms that a token holder has started; `0` requires a token for everyone. Recreate the containers after changing it.

## Everyone gets moderator rights

Authenticated users are moderators by default. Whether `context.user.moderator: false` demotes someone depends on your release and Prosody modules. Test with a host token and a guest token in two browsers before relying on it.

## Still failing?

Send us a token with the signature removed (never the secret) and the Prosody log lines, and we will spot the mismatch. We also build [Jitsi JWT integrations](/services/jitsi-integration/) end to end.

## Frequently asked questions

### How do I decode a Jitsi JWT to check it?

Split it on the dots and base64url-decode the middle part, or paste it into a JWT debugger you trust. Never paste the secret anywhere. Compare iss, aud, sub, room and exp with your server settings.

### Why is everyone a moderator with JWT?

With authentication enabled, Jicofo treats authenticated users as moderators unless your release and Prosody modules honour the context.user.moderator flag. Test with a guest token set to false; if it still gets moderator rights, you need the token affiliation module or a newer release.


---

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.
