Banning Player Tokens, duplicated tokens across multiple players

Hey, so we implemented a custom banning logic. Probably everyone does.
Recently we came across an issue which seemed kinda odd. We banned 2 players (reason is not relevant) but those 2 players shared an token and another two players share exact the same token. So a player can have many tokens (GetPlayerToken - FiveM Natives @ Cfx.re Docs) and we’r banning all of them individually. Now we have 4 players sharing a single token. I removed a ban in mid december which caused the 2 other players to play again. On 29th december we banned a modder which had the same duplicated token as the first one we banned and the same token the other 2 players are sharing. I guess sharing the token does not help but pointing out the issue may help?

The code for banning looks like this:

kickandbanuser = function(reason, servertarget)
    local target = tostring(source) == "" and tonumber(servertarget) or source
    local duration = 0
    local reason = reason or "Not Specified"


    if target and target > 0 then
        local ping = GetPlayerPing(target)

        if ping and ping > 0 then
            local sourceplayername = "AntiCheat"
            local targetplayername = GetPlayerName(target)
            local identifier, license, xblid, playerip, discord, liveid = getidentifiers(target) -- extract ids from target
            
            local token = {}
            for i = 0, GetNumPlayerTokens(target) do
                table.insert(token, GetPlayerToken(target, i))
            end

            ban_user(target,token,license,identifier,liveid,xblid,discord,playerip,targetplayername,sourceplayername,0,reason,1)
            DropPlayer(target, "[AntiCheat]:" .. reason)
        end
    end
end

ban_user = function(source,token,license,identifier,liveid,xblid,discord,playerip,targetplayername,sourceplayername,duration,reason,permanent)
    if not IsPlayerAceAllowed(source, "vbacbypass") and not IsPlayerAceAllowed(source, "vbacadmin") then
        local expiration = duration * 86400
        local timeat     = os.time()
        if expiration < os.time() then
            expiration = os.time()+expiration
        end
        MySQL.Async.execute('INSERT INTO bans (token,license,identifier,liveid,xblid,discord,playerip,targetplayername,sourceplayername,reason,expiration,timeat,permanent) VALUES (@token,@license,@identifier,@liveid,@xblid,@discord,@playerip,@targetplayername,@sourceplayername,@reason,@expiration,@timeat,@permanent)',{
            ['@token']          = json.encode(token),
            ['@license']          = license,
            ['@identifier']       = identifier,
            ['@liveid']           = liveid,
            ['@xblid']            = xblid,
            ['@discord']          = discord,
            ['@playerip']         = playerip,
            ['@targetplayername'] = targetplayername,
            ['@sourceplayername'] = sourceplayername,
            ['@reason']           = reason,
            ['@expiration']       = expiration,
            ['@timeat']           = timeat,
            ['@permanent']        = permanent,
            }, function ()
        end, function() loadBanList() end)
    end
end

On player connect i just go through all bans and check all the identifiers and tokens and if one of them is banned, the connection is denied. The documentation recommends to use the native GetPlayerToken - FiveM Natives @ Cfx.re Docs to improve banning. We never had any issues until december last year.

We were on b11509 and i updated to 12208 today, i’ll monitor it further.