This repo includes a working base implementation in
server.jsandclient.js.
Those files mirror the example logic below and are meant as a clean starting point so you can plug in your own DB, permissions, logging, and extra checks without touching the example here.
This guide is for people who actually want to learn how to build a proper authenticator — not those who slap Math.random() on a password and call it "unbypassable."
In this README, you’ll understand why things work, and you’ll get starter code you can expand on.
If you want to protect your script, extension, app, or game mod, this gives you the core ideas.
Please Star This Project If You Find It Useful :D
- What an authenticator actually is and why bad ones fail
- How to design one that isn’t garbage
- Basic server + client structure (clean, expandable, not bloated)
- Tips to avoid the classic security mistakes almost everyone makes
This is not a copy‑paste “paste this and you’re safe” guide. You’ll actually understand the logic behind everything.
A real authenticator should:
- Run security logic on the server (client = untrustworthy)
- Verify identity using something unique (Discord ID, fingerprint, API key, etc.)
- Issue time-limited tokens instead of trusting the client forever
- Refuse invalid, expired, or mismatched tokens
- Not leak logic, keys, or secrets into client-side code
If your client knows something, assume an attacker can know it too.
Here are the most common sins:
- Password hardcoded in the client (instant bypass)
- “Encryption” that’s just Base64
- Tokens that aren’t tied to the user
- Random strings with no server database
- Everything handled client-side
- Webhook-based login (PLEASE no😭)
If your authenticator breaks by pressing F12, it never worked.
Your authenticator should work like this:
client > server: I want a token
server > client: ok, but prove who you are
client > server: here’s my ID + fingerprint
server checks: valid? has permission?
server > client: here’s a temp token
client uses token to load code
server validates token on every request
All real checks happen on the server, never the client because in client it can be tampered.
This is not production-grade, it’s clean starter code you can expand (or use the file's as listed in this repo).
It uses:
- Express
- Simple in-memory store (swap for Mongo/SQLite later)
- Token validation
import express from "express";
import crypto from "crypto";
const app = express();
app.use(express.json());
const activeTokens = new Map();
// generate a token tied to user + fingerprint
function CreateToken(userId, fp) {
const token = crypto.randomBytes(24).toString("hex");
activeTokens.set(token, {
userId,
fp,
expires: Date.now() + 1000 * 60 * 60,
});
return token;
}
app.post("/auth", (req, res) => {
const { userId, fingerprint } = req.body;
if (!userId || !fingerprint) return res.status(400).json({ ok: false });
// you would check DB here
const token = CreateToken(userId, fingerprint);
res.json({ ok: true, token });
});
app.post("/validate", (req, res) => {
const { token, fingerprint } = req.body;
const data = activeTokens.get(token);
if (!data) return res.json({ ok: false });
if (data.expires < Date.now()) return res.json({ ok: false });
if (data.fp !== fingerprint) return res.json({ ok: false });
return res.json({ ok: true });
});
app.listen(3000, () => console.log("Auth server running"));Clean. Simple. Does the job, But can be improved.
async function Authenticate(userId, fingerprint) {
const res = await fetch("https://your-server.com/auth", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ userId, fingerprint }),
});
const data = await res.json();
if (!data.ok) throw new Error("Auth failed");
return data.token;
}
async function ValidateToken(token, fingerprint) {
const res = await fetch("https://your-server.com/validate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token, fingerprint }),
});
return (await res.json()).ok;
}Do this:
- Use short token lifetimes
- Rotate tokens often
- Keep code modular (optional, but makes it easier to edit in the future)
- Never trust client input
- Log attempts
- Rate-limit endpoints
Do NOT do this:
- Put API keys in the client
- Do validation only on the client
- Use Discord webhook “auth”
- Hardcode secrets or IDs
- Think obfuscation = security
Obfuscation is a speed bump, not a firewall.
If you want to protect something you built and you care about security even a little, this will give you a better foundation than 99% of the “authenticators” floating around Discord.
You can expand this, modify it, or rewrite it — but at least now you understand how and why it works.