#pragma once #include "auth/srp.hpp" #include "auth/auth_packets.hpp" #include #include #include #include namespace wowee { namespace network { class TCPSocket; class Packet; } namespace auth { struct Realm; // Authentication state enum class AuthState { DISCONNECTED, CONNECTED, CHALLENGE_SENT, CHALLENGE_RECEIVED, PIN_REQUIRED, AUTHENTICATOR_REQUIRED, PROOF_SENT, AUTHENTICATED, REALM_LIST_REQUESTED, REALM_LIST_RECEIVED, FAILED }; // Authentication callbacks using AuthSuccessCallback = std::function& sessionKey)>; using AuthFailureCallback = std::function; using RealmListCallback = std::function& realms)>; class AuthHandler { public: AuthHandler(); ~AuthHandler(); // Connection bool connect(const std::string& host, uint16_t port = 3724); void disconnect(); bool isConnected() const; // Authentication void authenticate(const std::string& username, const std::string& password); void authenticate(const std::string& username, const std::string& password, const std::string& pin); void authenticateWithHash(const std::string& username, const std::vector& authHash); void authenticateWithHash(const std::string& username, const std::vector& authHash, const std::string& pin); // Optional: when the auth server requires a PIN (securityFlags & 0x01), call this to continue. // PIN must be 4-10 digits. void submitPin(const std::string& pin); // Generic continuation for PIN / authenticator-required servers. void submitSecurityCode(const std::string& code); // Set client version info (call before authenticate) void setClientInfo(const ClientInfo& info) { clientInfo = info; } const ClientInfo& getClientInfo() const { return clientInfo; } // Realm list void requestRealmList(); const std::vector& getRealms() const { return realms; } // State AuthState getState() const { return state; } const std::vector& getSessionKey() const { return sessionKey; } const std::string& getUsername() const { return username; } // Callbacks void setOnSuccess(AuthSuccessCallback callback) { onSuccess = callback; } void setOnFailure(AuthFailureCallback callback) { onFailure = callback; } void setOnRealmList(RealmListCallback callback) { onRealmList = callback; } // Update (call each frame) void update(float deltaTime); private: void sendLogonChallenge(); void handleLogonChallengeResponse(network::Packet& packet); void sendLogonProof(); void handleLogonProofResponse(network::Packet& packet); void sendRealmListRequest(); void handleRealmListResponse(network::Packet& packet); void handlePacket(network::Packet& packet); void setState(AuthState newState); void fail(const std::string& reason); std::unique_ptr socket; std::unique_ptr srp; AuthState state = AuthState::DISCONNECTED; std::string username; std::string password; ClientInfo clientInfo; std::vector sessionKey; std::vector realms; // Callbacks AuthSuccessCallback onSuccess; AuthFailureCallback onFailure; RealmListCallback onRealmList; // Receive buffer std::vector receiveBuffer; // Challenge security extension (PIN) uint8_t securityFlags_ = 0; uint32_t pinGridSeed_ = 0; std::array pinServerSalt_{}; // from LOGON_CHALLENGE response std::array checksumSalt_{}; // from LOGON_CHALLENGE response (integrity salt) std::string pendingSecurityCode_; }; } // namespace auth } // namespace wowee