From 958a991ecf6ddaadca63b754bc93f881a363ebb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com> Date: Fri, 14 Aug 2020 11:24:49 -0400 Subject: [PATCH] server account manager: authenticate account Change-Id: I962a9423ca29f6e7d5c59896c326edeb954afe1a --- src/jamidht/server_account_manager.cpp | 122 +++++++++++++------------ src/jamidht/server_account_manager.h | 5 +- 2 files changed, 69 insertions(+), 58 deletions(-) diff --git a/src/jamidht/server_account_manager.cpp b/src/jamidht/server_account_manager.cpp index 1d9c5e2036..08d2a32cd2 100644 --- a/src/jamidht/server_account_manager.cpp +++ b/src/jamidht/server_account_manager.cpp @@ -29,6 +29,8 @@ #include <algorithm> #include <string_view> +using namespace std::literals; + namespace jami { using Request = dht::http::Request; @@ -209,6 +211,24 @@ ServerAccountManager::initAuthentication(PrivateKey key, }); } +void +ServerAccountManager::onAuthEnded(const Json::Value& json, const dht::http::Response& response, TokenScope expectedScope) +{ + if (response.status_code >= 200 && response.status_code < 300) { + auto scopeStr = json["scope"].asString(); + auto scope = scopeStr == "DEVICE"sv ? TokenScope::Device + : (scopeStr == "USER"sv ? TokenScope::User + : TokenScope::None); + auto expires_in = json["expires_in"].asLargestUInt(); + auto expiration = std::chrono::steady_clock::now() + std::chrono::seconds(expires_in); + JAMI_WARN("[Auth] Got server response: %d %s", response.status_code, response.body.c_str()); + setToken(json["access_token"].asString(), scope, expiration); + } else { + authFailed(expectedScope, response.status_code); + } + clearRequest(response.request); +} + void ServerAccountManager::authenticateDevice() { @@ -217,37 +237,30 @@ ServerAccountManager::authenticateDevice() } const std::string url = managerHostname_ + JAMI_PATH_LOGIN; JAMI_WARN("[Auth] getting a device token: %s", url.c_str()); - auto request = std::make_shared<Request>( - *Manager::instance().ioContext(), - url, - Json::Value {Json::objectValue}, - [onAsync = onAsync_](Json::Value json, const dht::http::Response& response) { - onAsync([=](AccountManager& accountManager) { - auto& this_ = *static_cast<ServerAccountManager*>(&accountManager); - if (response.status_code >= 200 && response.status_code < 300) { - auto scopeStr = json["scope"].asString(); - auto scope = scopeStr == "DEVICE" - ? TokenScope::Device - : (scopeStr == "USER" ? TokenScope::User : TokenScope::None); - auto expires_in = json["expires_in"].asLargestUInt(); - auto expiration = std::chrono::steady_clock::now() - + std::chrono::seconds(expires_in); - JAMI_WARN("[Auth] Got server response: %d %s", - response.status_code, - response.body.c_str()); - this_.setToken(json["access_token"].asString(), scope, expiration); - } else { - this_.authFailed(TokenScope::Device, response.status_code); - } - this_.clearRequest(response.request); - }); - }, - logger_); + auto request = std::make_shared<Request>(*Manager::instance().ioContext(), url, Json::Value{Json::objectValue}, [onAsync = onAsync_](Json::Value json, const dht::http::Response& response) { + onAsync([=] (AccountManager& accountManager) { + static_cast<ServerAccountManager*>(&accountManager)->onAuthEnded(json, response, TokenScope::Device); + }); + }, logger_); request->set_identity(info_->identity); // request->set_certificate_authority(info_->identity.second->issuer->issuer); sendRequest(request); } +void +ServerAccountManager::authenticateAccount(const std::string& username, const std::string& password) +{ + const std::string url = managerHostname_ + JAMI_PATH_LOGIN; + JAMI_WARN("[Auth] getting a device token: %s", url.c_str()); + auto request = std::make_shared<Request>(*Manager::instance().ioContext(), url, Json::Value{Json::objectValue}, [onAsync = onAsync_] (Json::Value json, const dht::http::Response& response){ + onAsync([=] (AccountManager& accountManager) { + static_cast<ServerAccountManager*>(&accountManager)->onAuthEnded(json, response, TokenScope::User); + }); + }, logger_); + request->set_auth(username, password); + sendRequest(request); +} + void ServerAccountManager::sendRequest(const std::shared_ptr<dht::http::Request>& request) { @@ -311,7 +324,7 @@ ServerAccountManager::setToken(std::string token, tokenExpire_ = expiration; nameDir_.get().setToken(token_); - if (not token_.empty()) { + if (not token_.empty() and scope != TokenScope::None) { auto& reqQueue = getRequestQueue(scope); JAMI_DBG("[Auth] Got token with scope %d, handling %zu pending requests", (int) scope, @@ -341,14 +354,17 @@ ServerAccountManager::sendDeviceRequest(const std::shared_ptr<dht::http::Request } void -ServerAccountManager::sendAccountRequest(const std::shared_ptr<dht::http::Request>& req) +ServerAccountManager::sendAccountRequest(const std::shared_ptr<dht::http::Request>& req, const std::string& pwd) { std::lock_guard<std::mutex> lock(tokenLock_); if (hasAuthorization(TokenScope::User)) { setAuthHeaderFields(*req); sendRequest(req); } else { - pendingAccountRequests_.emplace(req); + auto& rQueue = getRequestQueue(TokenScope::User); + if (rQueue.empty()) + authenticateAccount(info_->username, pwd); + rQueue.emplace(req); } } @@ -445,35 +461,29 @@ ServerAccountManager::revokeDevice(const std::string& password, return false; } const std::string url = managerHostname_ + PATH_DEVICE + "?deviceId=" + device; - JAMI_WARN("[Revoke] Removing device of %s at %s", info_->username.c_str(), url.c_str()); - auto request = std::make_shared<Request>( - *Manager::instance().ioContext(), - url, - [cb, onAsync = onAsync_](Json::Value json, const dht::http::Response& response) { - onAsync([=](AccountManager& accountManager) { - JAMI_DBG("[Revoke] Got request callback with status code=%u", response.status_code); - auto& this_ = *static_cast<ServerAccountManager*>(&accountManager); - if (response.status_code >= 200 && response.status_code < 300) { - try { - JAMI_WARN("[Revoke] Got server response"); - if (json["errorDetails"].empty()) { - if (cb) - cb(RevokeDeviceResult::SUCCESS); - this_.syncDevices(); - } - } catch (const std::exception& e) { - JAMI_ERR("Error when loading device list: %s", e.what()); + JAMI_WARN("[Revoke] Revoking device of %s at %s", info_->username.c_str(), url.c_str()); + auto request = std::make_shared<Request>(*Manager::instance().ioContext(), url, [cb, onAsync = onAsync_] (Json::Value json, const dht::http::Response& response){ + onAsync([=] (AccountManager& accountManager) { + JAMI_DBG("[Revoke] Got request callback with status code=%u", response.status_code); + auto& this_ = *static_cast<ServerAccountManager*>(&accountManager); + if (response.status_code >= 200 && response.status_code < 300) { + try { + JAMI_WARN("[Revoke] Got server response"); + if (json["errorDetails"].empty()) { + if (cb) + cb(RevokeDeviceResult::SUCCESS); + this_.syncDevices(); } - } else if (cb) - cb(RevokeDeviceResult::ERROR_NETWORK); - this_.clearRequest(response.request); - }); - }, - logger_); + } catch (const std::exception& e) { + JAMI_ERR("Error when loading device list: %s", e.what()); + } + } else if (cb) + cb(RevokeDeviceResult::ERROR_NETWORK); + this_.clearRequest(response.request); + }); + }, logger_); request->set_method(restinio::http_method_delete()); - request->set_auth(info_->username, password); - JAMI_DBG("[Revoke] Sending revoke device '%s' to JAMS", device.c_str()); - sendRequest(request); + sendAccountRequest(request, password); return false; } diff --git a/src/jamidht/server_account_manager.h b/src/jamidht/server_account_manager.h index 89e2d613d2..55dc1273b3 100644 --- a/src/jamidht/server_account_manager.h +++ b/src/jamidht/server_account_manager.h @@ -108,12 +108,13 @@ private: void setAuthHeaderFields(dht::http::Request& request) const; void sendDeviceRequest(const std::shared_ptr<dht::http::Request>& req); - void sendAccountRequest(const std::shared_ptr<dht::http::Request>& req); + void sendAccountRequest(const std::shared_ptr<dht::http::Request>& req, const std::string& password); void authenticateDevice(); - void authenticateAccount(); + void authenticateAccount(const std::string& username, const std::string& password); void authFailed(TokenScope scope, int code); void authError(TokenScope scope); + void onAuthEnded(const Json::Value& json, const dht::http::Response& response, TokenScope scope); void setToken(std::string token, TokenScope scope, -- GitLab