20#include "Client/api/client/v2/authentication_listener.pb.h"
21#include "Client/challenge_service.pb.h"
29#include <rapidjson/document.h>
36 std::string_view locale,
uint32 applicationVersion, std::string_view deviceId)
40 TC_LOG_DEBUG(
"session",
"[Battlenet::Authentication::LogonRequest] {} attempted to log in with game other than WoW (using {})!", session->
GetClientInfo(), program);
46 TC_LOG_DEBUG(
"session",
"[Battlenet::Authentication::LogonRequest] {} attempted to log in from an unsupported platform (using {})!", session->
GetClientInfo(), platform);
52 TC_LOG_DEBUG(
"session",
"[Battlenet::Authentication::LogonRequest] {} attempted to log in with unsupported locale (using {})!", session->
GetClientInfo(), locale);
61 rapidjson::Document doc;
62 doc.Parse(deviceId.data(), deviceId.length());
63 if (doc.HasParseError())
66 auto itr = doc.FindMember(
"UTCO");
67 if (itr == doc.MemberEnd())
70 if (!itr->value.IsUint())
76 session->
OnLogon(platform, locale, applicationVersion, timezoneOffset);
81 std::function<
void(
uint32)> sendResponse, std::function<
void(
AccountInfo const*, std::string_view)> sendLogonComplete)
86 std::shared_ptr<AccountInfo> accountInfo = std::make_shared<AccountInfo>();
91 sendResponse(ERROR_DENIED);
95 accountInfo->LoadResult(result);
97 if (accountInfo->LoginTicketExpiry < time(
nullptr))
109 if (characterCountsResult)
113 Field* fields = characterCountsResult->Fetch();
114 accountInfo->GameAccounts[fields[0].
GetUInt32()]
117 }
while (characterCountsResult->NextRow());
124 .WithPreparedCallback([session, accountInfo, sendResponse, sendLogonComplete](
PreparedQueryResult lastPlayerCharactersResult)
126 if (lastPlayerCharactersResult)
130 Field* fields = lastPlayerCharactersResult->Fetch();
133 .LastPlayedCharacters[realmId.GetSubRegionAddress()];
135 lastPlayedCharacter.
RealmId = realmId;
140 }
while (lastPlayerCharactersResult->NextRow());
145 std::string ipCountry;
147 ipCountry = location->CountryCode;
150 if (accountInfo->IsLockedToIP)
152 TC_LOG_DEBUG(
"session",
"[Session::HandleVerifyWebCredentials] Account '{}' is locked to IP - '{}' is logging in from '{}'",
153 accountInfo->Login, accountInfo->LastIP, ip_address);
155 if (accountInfo->LastIP != ip_address)
163 TC_LOG_DEBUG(
"session",
"[Session::HandleVerifyWebCredentials] Account '{}' is not locked to ip", accountInfo->Login);
164 if (accountInfo->LockCountry.empty() || accountInfo->LockCountry ==
"00")
165 TC_LOG_DEBUG(
"session",
"[Session::HandleVerifyWebCredentials] Account '{}' is not locked to country", accountInfo->Login);
166 else if (!accountInfo->LockCountry.empty() && !ipCountry.empty())
168 TC_LOG_DEBUG(
"session",
"[Session::HandleVerifyWebCredentials] Account '{}' is locked to country: '{}' Player country is '{}'",
169 accountInfo->Login, accountInfo->LockCountry, ipCountry);
171 if (ipCountry != accountInfo->LockCountry)
180 if (accountInfo->IsBanned)
182 if (accountInfo->IsPermanenetlyBanned)
184 TC_LOG_DEBUG(
"session",
"{} [Session::HandleVerifyWebCredentials] Banned account {} tried to login!", session->
GetClientInfo(), accountInfo->Login);
190 TC_LOG_DEBUG(
"session",
"{} [Session::HandleVerifyWebCredentials] Temporarily banned account {} tried to login!", session->
GetClientInfo(), accountInfo->Login);
197 sendLogonComplete(accountInfo.get(), ipCountry);
205uint32 Authentication::HandleGenerateAuthToken(
Session* session, std::function<
void(std::string_view)> sendResponse)
213 sendResponse((*result)[0].GetStringView());
229 std::string_view deviceId;
231 if (request->has_device_id())
232 deviceId = request->device_id();
237 if (request->has_cached_web_credentials())
240 challenge::v1::ChallengeExternalRequest externalChallenge;
241 externalChallenge.set_payload_type(
"web_auth_url");
252 if (!request->has_web_credentials())
259 std::function<
void(
ServiceBase*,
uint32, google::protobuf::Message
const*)>& continuation)
263 Authentication asyncContinuationService(session);
265 continuation(&asyncContinuationService, result, &response);
269 authentication::v1::LogonResult logonResult;
270 logonResult.set_error_code(0);
271 logonResult.mutable_account_id()->set_low(accountInfo->Id);
272 logonResult.mutable_account_id()->set_high(
UI64LIT(0x100000000000000));
273 for (
auto const& [
id, gameAccountInfo] : accountInfo->GameAccounts)
275 EntityId* gameAccountId = logonResult.add_game_account_id();
276 gameAccountId->set_low(gameAccountInfo.Id);
277 gameAccountId->set_high(
UI64LIT(0x200000200576F57));
280 if (!country.empty())
281 logonResult.set_geoip_country(country.data(), country.size());
283 std::array<uint8, 64> k = Trinity::Crypto::GetRandomBytes<64>();
284 logonResult.set_session_key(k.data(), 64);
286 Service<authentication::v1::AuthenticationListener>(session).OnLogonComplete(&logonResult);
298 authentication::v1::GenerateWebCredentialsResponse response;
299 response.set_web_credentials(webCredentials.data(), webCredentials.size());
300 continuation(&asyncContinuationService,
ERROR_OK, &response);
312 std::function<
void(
ServiceBase*,
uint32, google::protobuf::Message
const*)>& continuation)
315 std::string_view deviceId;
316 std::string_view cachedAuthToken;
318 if (request->has_logon_options())
320 authentication::v2::client::LogonOptions
const& logonOptions = request->logon_options();
321 if (logonOptions.has_device_id())
322 deviceId = logonOptions.device_id();
324 if (logonOptions.has_auth_token())
325 cachedAuthToken = logonOptions.auth_token();
331 if (!cachedAuthToken.empty())
334 authentication::v2::client::ExternalChallengeNotification externalChallenge;
335 externalChallenge.set_payload_type(
"web_auth_url");
345 std::function<
void(
ServiceBase*,
uint32, google::protobuf::Message
const*)>& continuation)
347 if (!request->has_auth_token())
354 authentication::v2::client::GenerateAuthTokenResponse* , std::function<
void(
ServiceBase*,
uint32, google::protobuf::Message
const*)>& continuation)
362 authentication::v2::client::GenerateAuthTokenResponse response;
363 response.set_auth_token(webCredentials.data(), webCredentials.size());
364 continuation(&asyncContinuationService,
ERROR_OK, &response);
374 continuation(&asyncContinuationService, result, &response);
378 authentication::v2::client::LogonCompleteNotification logonResult;
379 logonResult.set_error_code(0);
380 authentication::v2::client::LogonRecord* logonRecord = logonResult.mutable_record();
381 logonRecord->set_account_id(accountInfo->Id);
382 for (
auto const& [
id, gameAccountInfo] : accountInfo->GameAccounts)
384 account::v2::GameAccountHandle* gameAccount = logonRecord->add_game_account();
385 gameAccount->set_id(gameAccountInfo.Id);
387 gameAccount->set_region(2);
390 if (!country.empty())
391 logonRecord->set_geoip_country(country.data(), country.size());
393 std::array<uint8, 64> k = Trinity::Crypto::GetRandomBytes<64>();
394 logonRecord->set_session_key(k.data(), 64);
@ ERROR_GAME_ACCOUNT_BANNED
@ ERROR_RISK_ACCOUNT_LOCKED
@ ERROR_GAME_ACCOUNT_SUSPENDED
LocaleConstant GetLocaleByName(std::string_view name)
constexpr bool IsValidLocale(LocaleConstant locale)
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< LoginDatabaseConnection > LoginDatabase
Accessor to the realm/login database.
std::chrono::minutes Minutes
Minutes shorthand typedef.
#define TC_LOG_DEBUG(filterType__, message__,...)
@ LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_BNET_ID
@ LOGIN_SEL_BNET_EXISTING_AUTHENTICATION_BY_ID
@ LOGIN_SEL_BNET_ACCOUNT_INFO
@ LOGIN_SEL_BNET_LAST_PLAYER_CHARACTERS
static uint32 HandleVerifyAuthToken(Session *session, std::string_view authToken, std::function< void(uint32)> sendResponse, std::function< void(AccountInfo const *, std::string_view)> sendLogonComplete)
static uint32 HandleLogon(Session *session, ClientBuild::Program::Id program, std::string_view platform, std::string_view locale, uint32 applicationVersion, std::string_view deviceId)
static uint32 HandleGenerateAuthToken(Session *session, std::function< void(std::string_view)> sendResponse)
uint32 HandleGenerateWebCredentials(authentication::v1::GenerateWebCredentialsRequest const *request, authentication::v1::GenerateWebCredentialsResponse *response, std::function< void(ServiceBase *, uint32, google::protobuf::Message const *)> &continuation) override
uint32 HandleVerifyWebCredentials(authentication::v1::VerifyWebCredentialsRequest const *request, NoData *response, std::function< void(ServiceBase *, uint32, ::google::protobuf::Message const *)> &continuation) override
uint32 HandleLogon(authentication::v1::LogonRequest const *request, NoData *response, std::function< void(ServiceBase *, uint32, ::google::protobuf::Message const *)> &continuation) override
uint32 HandleLogon(authentication::v2::client::LogonRequest const *request, NoData *response, std::function< void(ServiceBase *, uint32, ::google::protobuf::Message const *)> &continuation) override
Authentication(Session *session)
uint32 HandleVerifyAuthToken(authentication::v2::client::VerifyAuthTokenRequest const *request, NoData *response, std::function< void(ServiceBase *, uint32, ::google::protobuf::Message const *)> &continuation) override
uint32 HandleGenerateAuthToken(authentication::v2::client::GenerateAuthTokenRequest const *request, authentication::v2::client::GenerateAuthTokenResponse *response, std::function< void(ServiceBase *, uint32, google::protobuf::Message const *)> &continuation) override
std::string GetClientInfo() const
uint32 GetAccountId() const
void OnLogon(std::string_view platform, std::string_view locale, uint32 applicationVersion, Minutes timezoneOffset)
void QueueQuery(QueryCallback &&queryCallback)
void OnLogonSuccess(std::shared_ptr< AccountInfo > accountInfo, std::string_view ipCountry)
boost::asio::ip::address const & GetRemoteIpAddress() const
static bool UsesDevWildcardCertificate()
Class used to access individual fields of database query result.
uint64 GetUInt64() const noexcept
uint32 GetUInt32() const noexcept
uint8 GetUInt8() const noexcept
std::string GetString() const noexcept
void setString(uint8 index, std::string &&value)
void setUInt32(uint8 index, uint32 value)
void SetNextQuery(QueryCallback &&next)
Minutes GetOffsetByHash(uint32 hash)
std::string StringFormat(FormatString< Args... > fmt, Args &&... args) noexcept
Default TC string format function.
Battlenet::RealmHandle RealmId
std::string CharacterName
static constexpr FourCC FromString(std::string_view text)