Files
DarkflameServer/dDashboardServer/auth/DashboardAuthService.h
Aaron Kimbrell e213a7aeff feat: web dashboard and playground work
The NexusDashboard-parity dashboard (dDashboardServer) and everything built on it on the experimental branch:
accounts, characters, properties and moderation tools, permissions shared with in-game slash commands, economy
reports, World 3D and property 3D views with client scenery, scheduled events (features, vanity changes, live
events, announcements, restarts), vanity files and events, the CDClient browser, the message inspector with saved
captures, chat filter tools, community challenges, live ops, the AI moderator helper, and the server-side changes
they need.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:30:43 -05:00

85 lines
3.5 KiB
C++

#pragma once
#include <string>
#include <cstdint>
/**
* Dashboard authentication service
* Handles user login, password verification, and account lockout
*/
class DashboardAuthService {
public:
/**
* Login result structure
*/
struct LoginResult {
bool success{false};
std::string message{};
std::string token{}; // JWT token if successful
uint8_t gmLevel{0}; // GM level if successful
bool accountLocked{false}; // Account is locked out
bool twoFactorRequired{false}; // Password was right; finish with CompleteTwoFactor(challenge, code)
std::string challenge{};
bool usedRecoveryCode{false};
uint32_t accountId{0};
};
/**
* Attempt to log in with username and password
* @param username The username
* @param password The plaintext password (max 40 characters)
* @param rememberMe If true, extends token expiration to 30 days
* @param address The client's network address; failed attempts are throttled per (address, account)
* @return LoginResult with success status and JWT token if successful
*/
static LoginResult Login(const std::string& username, const std::string& password, bool rememberMe, const std::string& address);
/**
* Second step of logging in to an account with two-factor login: a code from the authenticator app, or one of
* the account's recovery codes. A challenge is valid for 5 minutes and a few attempts.
*/
static LoginResult CompleteTwoFactor(const std::string& challenge, const std::string& code);
/**
* Check a two-factor code for an account (authenticator code, or a recovery code when allowRecovery).
* Each authenticator code and recovery code is accepted only once.
*/
static bool CheckTwoFactorCode(uint32_t accountId, const std::string& code, bool allowRecovery, bool* usedRecoveryCode = nullptr);
// Count a failed attempt (wrong password or code) from an address. Returns whether that address is now blocked
// from the account (or the whole account is briefly locked after many failures from everywhere).
static bool RecordFailedAttempt(uint32_t accountId, const std::string& username, const std::string& address);
// Whether sign-in attempts to the account from this address are currently refused
static bool IsThrottled(uint32_t accountId, const std::string& address);
// Forget failed attempts against an account (staff unlocked it)
static void ClearThrottle(uint32_t accountId);
// GM level from which two-factor login is mandatory (config require_2fa_gm_level), 0 when it is not required
static uint8_t RequiredTwoFactorLevel();
// Whether this account must set up two-factor login before using the dashboard
static bool NeedsTwoFactorSetup(uint32_t accountId, uint8_t gmLevel);
static std::string Sha256Hex(const std::string& text);
/**
* Verify that a token is valid and resolve the account it belongs to.
* The GM level comes from the database, not the token, so demotions and bans apply immediately.
* @param token The JWT token
* @param username Output parameter for the username
* @param gmLevel Output parameter for the account's current GM level
* @param accountId Output parameter for the account ID
* @return true if token is valid and the account may still use the dashboard
*/
static bool VerifyToken(const std::string& token, std::string& username, uint8_t& gmLevel, uint32_t& accountId);
/**
* Check if user has required GM level for dashboard access
* @param gmLevel The user's GM level
* @return true if user can access dashboard (GM level > 0)
*/
static bool HasDashboardAccess(uint8_t gmLevel);
};