Back to the catalog

Key System

Cookieskeysystem.lua · v2.0.0

A window that asks for a key before your hub loads, in the same style as CookiesLib. It checks against a list, a URL, your own function or KeyForge, remembers the key and locks after several failed attempts.

On this page

Try it before you use it

This script opens the Key System with a single valid key, COOKIES-DEMO (case-insensitive). Paste it into your executor and try a wrong key and a right one:

KeySystemTest.lua
local KeySystem = loadstring(game:HttpGet("https://raw.githubusercontent.com/Lilwero20/CookiesLib/main/Cookieskeysystem.lua"))()

local ok, key = KeySystem.Prompt({
    Title = "Test",
    Keys = { "COOKIES-DEMO" },
    CaseSensitive = false,
    SaveKey = false,
})

print("Key valid:", ok, key)

It's also inside the CookiesLib demo menu: open the Personalizar (Customize) tab and press Abrir key system. There the key is also COOKIES-DEMO, and 3 mistakes trigger a 10-second wait.

CookiesDemo.lua
loadstring(game:HttpGet("https://raw.githubusercontent.com/Lilwero20/CookiesLib/main/CookiesDemo.lua"))()

Quick start

Load the library and the Key System, ask for the key and, only if it's valid, create your window. If you pass Library, the Key System uses its theme (including the one the player picked) and its fonts.

lua
local Library   = loadstring(game:HttpGet("https://raw.githubusercontent.com/Lilwero20/CookiesLib/main/CookiesLib.lua"))()
local KeySystem = loadstring(game:HttpGet("https://raw.githubusercontent.com/Lilwero20/CookiesLib/main/Cookieskeysystem.lua"))()

local ok, key = KeySystem.Prompt({
    Library = Library,
    Title = "My Hub",
    Subtitle = "Key System",
    KeyLink = "https://example.com/get-key",
    DiscordLink = "https://discord.gg/xxxxxx",
    Keys = { "COOKIE-1234", "COOKIE-5678" },
})
if not ok then return end

local Window = Library:CreateWindow({ Title = "My Hub" })

KeySystem.Prompt(options) waits until the player validates or closes, and returns ok, key. It's a shortcut for KeySystem.new(options):Wait().

How the key is checked

The first available method is used, in this order:

  1. 1`KeyForge`: external key service (see below).
  2. 2`Validate`: your own function.
  3. 3`KeyUrl`: a URL with one key per line (cached for 30 seconds).
  4. 4`Keys`: a list inside the script.
lua
Validate = function(key)
    if key == "secret" then
        return true, "Welcome"
    end
    return false, "Wrong key"
end,

KeyUrl = "https://raw.githubusercontent.com/user/repo/main/keys.txt",

Validate returns whether the key is valid and, optionally, a message for the player. Spaces at the start and end of the key are ignored, and with CaseSensitive = false upper or lower case doesn't matter.

A Keys list inside the script can be read by anyone who opens the script. For anything serious use KeyUrl, Validate against your server, or KeyForge.

Customizing it

You can change the theme, the color, the texts and the help steps. This example gives it a pink theme and custom texts:

lua
KeySystem.new({
    Library = Library,
    Theme = "Strawberry",
    Accent = Color3.fromRGB(255, 105, 140),
    Title = "My Hub",
    Subtitle = "Access",
    Description = "Enter your key to unlock the hub.",
    Steps = {
        "Press Get key to copy the link",
        "Complete the steps in your browser",
        "Paste your key and press Verify",
    },
    Keys = { "COOKIE-1234" },
    CaseSensitive = false,
    MaxAttempts = 3,
    Cooldown = 10,
    Blur = true,
})
OptionDefaultWhat it does
LibrarynilInherits CookiesLib's theme and fonts
ThemenilName of a CookiesLib theme or a color table
AccentnilAccent color for the Key System only
Title / Subtitle"Cookies Hub" / "Key System"Header texts
LogoCookies logoImage; false removes it
DescriptionEnglish textText under the title
Steps3 English stepsUp to 3 steps in the “Need a key?” panel
NotenilFree text instead of the steps
KeyLinknilLink for the Get key button
DiscordLinknilJoin Discord button
CaseSensitivetruefalse ignores upper and lower case
SaveKeytrueAllows remembering the key on the device
AutoVerifytrueChecks the saved key automatically on open
MaxAttempts5Failed attempts before the lock
Cooldown15Lock duration in seconds
Blur / ShadowtrueBackground blur and window shadow
Folder / FileName"CookiesHub" / autoWhere the key is saved
IdautomaticKeeps each script's key and lock separate

Buttons only appear when they have something to do: Get key with KeyLink or KeyForge, Join Discord with DiscordLink, and Paste if the executor has clipboard access.

Object and events

KeySystem.new returns an object you can control from your script:

lua
local ks = KeySystem.new({ Keys = { "COOKIE-1234" } })

local ok, key = ks:Wait()
ks:Submit("COOKIE-1234")
ks:SetStatus("Checking...", "Warning")
ks:Close()
ks:Destroy()
MethodWhat it does
ks:Wait()Waits until it finishes and returns success, key
ks:Submit(key)Submits a key from code (no argument uses what's typed)
ks:SetStatus(text, type)Message under the button: Success, Warning, Error or nil
ks:Close()Closes without validating
ks:Destroy()Closes and cleans everything up

Instead of waiting with Wait() you can use events:

lua
KeySystem.new({
    Keys = { "COOKIE-1234" },
    OnSuccess = function(key)
        loadstring(game:HttpGet("https://example.com/my-hub.lua"))()
    end,
    OnFail = function(key, message)
        warn("Wrong key:", key, message)
    end,
    OnClose = function()
        warn("Closed without a key")
    end,
})

How it behaves

  • Remembered key: if the executor can save files, a *Remember key* checkbox appears. A valid key is saved and, next time, it's filled in and checked automatically. If it stops being valid, it's deleted.
  • Attempts: the remaining attempts are shown. When they run out, the button locks for Cooldown seconds, even if the script is re-run in the same game.
  • Connection errors (URL down, KeyForge not responding, an error in Validate) don't use up attempts.
  • The window can be dragged from the top and adapts to small screens.

Several scripts with keys

Each Key System has its own Id, so several scripts can use it at the same time without clashing: each saves its key in Folder/keys/<Id>.txt and has its own attempt lock.

If you useAutomatic `Id`
Id = "my-hub"my-hub
KeyForgekf_<scriptId>
KeyUrlurl_<URL hash>
Keyskeys_<list hash>
Only ValidateThe Title

If two of your scripts use Validate with the same Title, give them different Ids:

lua
KeySystem.new({ Id = "blox-fruits", Title = "Cookies Hub", Validate = check })
KeySystem.new({ Id = "steal-an-egg", Title = "Cookies Hub", Validate = check })

KeyForge

Optional integration with KeyForge, the service Cookies Hub uses. KeyForge handles key status, limits, HWID and script delivery. Its SDK downloads in the background when the window opens, so checking is almost instant.

lua
KeySystem.new({
    Library = Library,
    DiscordLink = "https://discord.gg/xxxxxx",
    KeyForge = {
        projectId = "YOUR_PROJECT_ID",
        scriptId = "YOUR_SCRIPT_ID",
        integrationToken = "YOUR_TOKEN",
    },
    LoadScript = true,
})

The IDs and the token come from the KeyForge dashboard: edit a keyed script, open In-game UI and choose Custom Lua GUI. Official KeyForge guide.

Button / momentCallWhat the window does
Get keyclient:getKeyUrl()Copies the key page link
Verifyclient:verify(key)Continues if valid; otherwise shows KeyForge's message
After validating (LoadScript = true)client:loadScript()Loads the protected script. If it fails, the window stays open and shows why
CodeMeaningUses an attempt?
KEY_INVALIDThe key doesn't exist or is emptyYes
KEY_EXPIREDThe key expiredYes (and the saved one is deleted)
KEY_REVOKEDThe key was revokedYes (and the saved one is deleted)
KEY_SCRIPT_MISMATCHThe key belongs to another scriptYes
HWID_MISMATCHThe key is tied to another deviceYes
RATE_LIMITEDToo many attempts on KeyForgeNo
SESSION_EXPIREDThe verification expiredNo
NETWORK_ERRORCouldn't connect to KeyForgeNo
PROJECT_DISABLEDProject disabled or pausedNo

Don't put secrets or validation rules inside your script: a dumped script can be read. Leave that to KeyForge or your server.

Full example

A Key System with the CookiesLib theme, 3 attempts and a 10-second wait, and a window that only appears with a valid key. The test key is COOKIES-DEMO:

MyHubWithKey.lua
local Library   = loadstring(game:HttpGet("https://raw.githubusercontent.com/Lilwero20/CookiesLib/main/CookiesLib.lua"))()
local KeySystem = loadstring(game:HttpGet("https://raw.githubusercontent.com/Lilwero20/CookiesLib/main/Cookieskeysystem.lua"))()

local ok, key = KeySystem.Prompt({
    Library = Library,
    Title = "My Hub",
    Subtitle = "Key System",
    KeyLink = "https://example.com/get-key",
    DiscordLink = "https://discord.gg/xxxxxx",
    Keys = { "COOKIES-DEMO" },
    CaseSensitive = false,
    SaveKey = false,
    MaxAttempts = 3,
    Cooldown = 10,
    OnFail = function(_, message)
        warn(message)
    end,
})
if not ok then return end

local Window = Library:CreateWindow({ Title = "My Hub", Subtitle = "Unlocked" })
local Main = Window:CreateTab("Main", "M")
local Welcome = Main:CreateSection({ Name = "Welcome", Full = true })
Welcome:AddAlert({ Type = "Success", Title = "Key accepted", Content = "Your key: <b>" .. key .. "</b>" })
Welcome:AddButton({ Name = "Say hi", Primary = true, Callback = function()
    Window:Notify({ Title = "My Hub", Content = "Hi!", Type = "Success" })
end })
Window:CreateSettingsTab()

Common problems

  • It doesn't remember the key: the executor must support writefile, readfile, isfolder, makefolder and isfile, and *Remember key* must be checked when validating.
  • The Get key button doesn't show up: it needs KeyLink or KeyForge.
  • I got locked and re-ran the script: the lock lasts Cooldown seconds even if you re-run in the same game; that's on purpose.
  • Two scripts delete each other's key: give each one a different Id.