RE:NODE

Guides11 min read

FiveM Discord whitelist and role permissions

Whitelist a FiveM server by Discord membership or role with txAdmin, and map Discord roles to ACE permissions with a small resource or an existing one.

0 readers

Discord on a FiveM server does two separate jobs, and it is easier once you stop treating them as one. The whitelist decides who may connect: txAdmin does this itself, by Discord server membership or by role, with nothing extra installed. Permissions decide what a connected player may do: that means turning Discord roles into ACE groups with add_principal identifier.discord:<id> group.<name> when they join, either with a ready-made resource or with forty lines of your own. Both need a Discord bot in your guild and both depend on the player's Discord identifier, which only exists if the Discord desktop app is running when they start FiveM. This guide sets up the bot, the txAdmin whitelist, the role-to-ACE mapping, and covers the failure cases you will meet in the first week.

How the pieces fit#

connectidentifiersis member, which rolesroles become groupsPlayerDiscord app runningFXServerplayerConnectingtxAdmin whitelistmember or roleACE groupsadd_principalDiscord botin your guild
A Discord-gated FiveM connection

When a player connects, FXServer collects their identifiers - license, discord, fivem, xbl, live, IP, and steam if you have set a Steam Web API key. The discord identifier is the player's Discord user ID, and it is only present when the Discord desktop client was running and logged in when FiveM started. Discord in a browser tab does not count.

The whitelist step asks Discord, through your bot, whether that user is in your guild and which roles they hold, and accepts or rejects the connection. The permissions step takes the same roles and adds the player's Discord identifier to ACE groups, so IsPlayerAceAllowed and ACE-restricted commands see them. txAdmin handles the first. The second is a resource, because txAdmin's own admin list governs its web panel and in-game menu, not ACE.

Creating the Discord bot#

Both steps need a bot account in your Discord server. It does not need to be online all the time as a separate program - txAdmin and the permission resource use its token to make requests.

  1. Open the Discord Developer Portal, create a New Application, and add a Bot to it.
  2. Copy the bot token. Treat it like a password: anyone holding it controls the bot and can read your member list.
  3. On the Bot page, enable the Server Members Intent. Member and role lookups depend on it, and forgetting it is the most common reason the whitelist rejects everyone.
  4. Under OAuth2, generate an invite URL with the bot scope and invite the bot to your guild. It needs no special permissions to read members and roles.
  5. In Discord, enable Developer Mode (User Settings, Advanced). Right-click your server and Copy Server ID, then right-click each role you care about and Copy Role ID.

You now have a token, a guild ID and a list of role IDs. Store the token in one place only. If you put it in server.cfg, use set, never sets or setr - sets publishes the value to the server list, where it will be scraped. Environment variables and secrets covers keeping it out of screenshots and repositories.

Whitelisting with txAdmin#

txAdmin has a built-in whitelist and a built-in Discord bot integration, so for the gate itself you need no resource.

  1. In txAdmin, open Settings and the Discord tab. Enable the bot, paste the token and the guild ID, and save. txAdmin connects and reports whether it could see the guild.
  2. Open the whitelist setting (under Settings, Player Manager in current versions) and pick a mode.
ModeWho gets in
DisabledEveryone not banned
Admin-onlytxAdmin admins only; useful for maintenance
Discord server memberAnyone in your Discord guild
Discord server rolesMembers holding at least one of the listed role IDs
Approved licensePlayers an admin has approved, one by one

The exact names shift a little between txAdmin versions, but those five behaviours have been stable.

Discord server roles is what most roleplay servers want: applicants join the Discord, pass an application, receive a "Whitelisted" role, and can connect from that moment. Removing the role removes access at their next connection. Paste the role IDs, not names; names can be duplicated and renamed, IDs cannot.

Approved license suits a small private server without a Discord process. A rejected player is shown a short request ID; an admin approves it from txAdmin's whitelist page or with the bot's whitelist command in Discord, and the player can join.

The rejection message is configurable. Make it tell players exactly what to do - "Join discord.gg/yourserver and complete the application" - and what to check if they believe they are whitelisted: is the Discord app open, and is it the right account. That one sentence saves dozens of support tickets.

Discord roles to ACE permissions#

The whitelist lets people in. To give a Discord role in-game powers - admin commands, a staff menu, a donor vehicle - you need ACE principals. The mechanism is the same one described in FiveM server.cfg explained: groups hold aces, and a principal joins a player identifier to a group.

permissions.cfg
add_ace group.admin command allowadd_ace group.admin command.quit denyadd_ace group.mod command.kick allowadd_principal group.admin group.mod

Static lines like add_principal identifier.discord:216735154273419264 group.admin work, but they do not follow role changes in Discord. A resource that adds principals when a player connects, based on their current roles, does.

The best-known ready-made option is the pair of resources by Badger: Badger_Discord_API, which talks to Discord, and DiscordAcePerms, which maps role IDs to groups at connect. They are widely used and well documented; follow their own README for the config format, because it has changed across versions.

If you would rather know exactly what is running, the job is small enough to write yourself:

discord_perms/server.lua
local GUILD = GetConvar("discord_guild_id", "")local TOKEN = GetConvar("discord_bot_token", "")-- Discord role ID -> ACE grouplocal ROLE_GROUPS = {    ["111111111111111111"] = "group.admin",    ["222222222222222222"] = "group.mod",    ["333333333333333333"] = "group.donor",}local function discordId(src)    local id = GetPlayerIdentifierByType(src, "discord")    return id and id:gsub("discord:", "")endAddEventHandler("playerConnecting", function(name, setKickReason, deferrals)    local src = source    deferrals.defer()    Wait(0)    deferrals.update("Checking your Discord roles...")    local id = discordId(src)    if not id then        deferrals.done("Open the Discord desktop app, then restart FiveM.")        return    end    local url = ("https://discord.com/api/v10/guilds/%s/members/%s"):format(GUILD, id)    PerformHttpRequest(url, function(status, body)        if status == 200 then            local member = json.decode(body)            for _, group in pairs(ROLE_GROUPS) do                ExecuteCommand(("remove_principal identifier.discord:%s %s"):format(id, group))            end            for _, role in ipairs(member.roles or {}) do                local group = ROLE_GROUPS[role]                if group then                    ExecuteCommand(("add_principal identifier.discord:%s %s"):format(id, group))                end            end        end        deferrals.done()    end, "GET", "", { Authorization = "Bot " .. TOKEN })end)

And in server.cfg:

config
set discord_guild_id "123456789012345678"set discord_bot_token "your-bot-token"add_ace resource.discord_perms command.add_principal allowadd_ace resource.discord_perms command.remove_principal allowensure discord_perms

The two add_ace resource. lines matter. A resource cannot run add_principal through ExecuteCommand unless it has been granted that command, and without them the script runs, prints nothing useful, and nobody gets their group.

Points about the code worth understanding rather than copying:

  • `deferrals.defer()` then `Wait(0)`. Deferring holds the connection while you do asynchronous work; the wait is required before calling update or done.
  • Removing before adding. Principals are keyed on the identifier and last until the server restarts, so a player who lost a role in Discord keeps the group unless you remove it. The loop clears every mapped group first.
  • A non-member still gets in here. This resource only maps permissions. Rejecting non-members is txAdmin's job; doing it in two places means two places to debug.
  • `GetPlayerIdentifierByType` is available on current server builds. On very old ones, loop over GetPlayerIdentifiers(src) instead.

Framework permissions are a third system#

ACE is FiveM's permission system, but frameworks layer their own on top, and they connect to it differently.

  • QBCore uses ACE directly. Its permission levels are ACE groups such as qbcore.god, qbcore.admin and qbcore.mod, so a Discord role mapped to qbcore.admin works with QBCore's admin checks. Check your version's config.lua for the exact names.
  • ESX stores a group value per player in its database (user, admin and so on) and checks that. Mapping a Discord role to an ACE group does not change the ESX group; you need a resource that sets it through the framework, or you set it by hand.
  • Qbox follows the QBCore approach and relies on ACE.

Before mapping roles, decide which of the three systems each permission belongs to, and write it down. "Why can the moderator open the admin menu but not kick anyone?" is almost always one system granting and another refusing. The framework side is covered in FiveM frameworks compared.

txAdmin admins and Discord#

txAdmin keeps its own admin accounts with their own permissions - who can kick, ban, restart, edit the config, use the in-game menu. Those accounts can be linked to a Discord ID and a FiveM identifier so the in-game menu recognises them, but txAdmin admin status and ACE groups remain separate. A senior moderator typically needs both: a txAdmin account with player-management permissions, and a Discord role that maps to group.mod for in-game commands.

Keep both lists short. Every person with ban rights can also unban; every person with config rights can read your database password. The same reasoning applies to the panel, where subusers and least privilege explains why console-only and files-only access exist. On RE:NODE, subusers can be given exactly that - console only, files only, no billing - and access can be time-boxed, which suits a developer you are letting in for a week.

Running the application process around it#

The technical whitelist is the easy half. The process that decides who receives the role is what makes a whitelisted server worth joining, and it is worth designing on purpose.

  • One role for access, separate roles for permissions. "Whitelisted" lets people connect. "Police", "EMS" and "Staff" grant things in game. Mixing them - letting the police role also grant access - means removing someone from the police also locks them out of the server.
  • An application channel or form. Most servers use a Discord form bot or a website form. Ask what you actually decide on: age, timezone, roleplay experience, a short character concept. Long essays filter out good players as well as bad ones.
  • Who can grant the role. Restrict role management in Discord to the people who review applications. Anyone who can grant "Whitelisted" controls your server's door, and anyone who can grant "Staff" controls everything behind it.
  • Removing access. Take the role away for bans that should outlast an in-game ban, and for players who leave your Discord. With the role whitelist, leaving the guild removes access automatically at the next connection.
  • Inactive players. Some servers prune the whitelisted role after months of inactivity to keep the community current. Tell players before you do it.

Write the rules down and pin them in the application channel. Server rules, moderation and staff covers the people side of this in more depth, including appeals.

Rate limits and reliability#

Discord rate-limits bots. One lookup per connecting player is well within the limits for any normal server, even at restart time when sixty people reconnect in two minutes. What causes trouble is checking roles repeatedly while players are online - on every command, every minute, every job change. Look roles up at connect, cache them for the session, and refresh only on demand.

If Discord does not answer, decide what happens. The code above lets the player in without groups, which is the safe failure for permissions. For a whitelist the trade-off is the other way: failing open lets anyone in during a Discord outage, failing closed keeps everyone out. txAdmin fails closed, which is right for a whitelist, and is why the Admin-only fallback matters.

Troubleshooting#

Everyone is rejected by the role whitelist. Server Members Intent is off, the bot is not in the guild, or the guild ID is wrong. txAdmin's Discord settings page reports whether the bot can see the guild.

One player is rejected despite having the role. Their Discord app was not running when FiveM started, they are logged into a different Discord account, or the account in the guild is not the one linked in their client. Ask them to close FiveM, open Discord, and start again.

Roles map but commands are still refused. The resource is missing its add_ace resource.<name> command.add_principal allow line, or the group has no aces granted for that command.

Removed staff keep their powers. Principals persist until restart. Remove before adding, as above, or restart the server.

Permissions work in game but not in txAdmin. They are different systems. Give the person a txAdmin account as well.

FAQ#

Do players need Discord open to join a Discord-whitelisted server?

Yes. The Discord identifier comes from the Discord desktop app running when FiveM starts. Without it, there is nothing to check, and a role-based whitelist rejects the connection.

Can I whitelist without installing a resource?

Yes. txAdmin's whitelist supports Discord server membership and Discord roles directly once its Discord bot is configured. Resources are only needed to turn roles into in-game ACE permissions.

Why use role IDs instead of role names?

Names can be changed or duplicated by anyone with role management rights, which would silently change who gets in. IDs are fixed for the life of the role.

Does giving someone admin in txAdmin make them an in-game admin?

Not in ACE terms. txAdmin admins can use txAdmin's own menu and panel, but ACE groups and framework groups are separate, and each has to be granted on its own.

What happens if my bot token leaks?

Reset it in the Developer Portal immediately and update it wherever it is stored. A leaked token lets anyone act as the bot and read your guild's member list.


Comments

Completely anonymous: no account, no email, no cookie. We store the name you type, the text and the time - nothing else. Links are limited and markup is not rendered.

0/2000