// // Created by stephane bourque on 2022-10-25. // #include "Poco/Net/HTTPServerResponse.h" #include "fmt/format.h" #include "framework/AuthClient.h" #include "framework/MicroServiceNames.h" #include "framework/OpenAPIRequests.h" #include "framework/utils.h" namespace OpenWifi { bool AuthClient::RetrieveTokenInformation(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy &UInfo, std::uint64_t TID, bool &Expired, bool &Contacted, bool Sub) { try { Types::StringPairVec QueryData; QueryData.push_back(std::make_pair("token", SessionToken)); std::string AlternateURIForLogging = fmt::format( "{}?token={}", Sub ? "/api/v1/validateSubToken" : "/api/v1/validateToken", Utils::SanitizeToken(SessionToken)); OpenAPIRequestGet Req(uSERVICE_SECURITY, Sub ? "/api/v1/validateSubToken" : "/api/v1/validateToken", QueryData, 10000, AlternateURIForLogging); Poco::JSON::Object::Ptr Response; auto StatusCode = Req.Do(Response); if (StatusCode == Poco::Net::HTTPServerResponse::HTTP_GATEWAY_TIMEOUT) { Contacted = false; return false; } Contacted = true; if (StatusCode == Poco::Net::HTTPServerResponse::HTTP_OK) { if (Response->has("tokenInfo") && Response->has("userInfo")) { UInfo.from_json(Response); if (IsTokenExpired(UInfo.webtoken)) { Expired = true; return false; } Expired = false; Cache_.update(SessionToken, UInfo); return true; } else { return false; } } } catch (...) { poco_error(Logger(), fmt::format("Failed to retrieve token={} for TID={}", Utils::SanitizeToken(SessionToken), TID)); } Expired = false; return false; } bool AuthClient::IsAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy &UInfo, std::uint64_t TID, bool &Expired, bool &Contacted, bool Sub) { auto User = Cache_.get(SessionToken); if (!User.isNull()) { if (IsTokenExpired(User->webtoken)) { Expired = true; Cache_.remove(SessionToken); return false; } Expired = false; UInfo = *User; return true; } return RetrieveTokenInformation(SessionToken, UInfo, TID, Expired, Contacted, Sub); } bool AuthClient::RetrieveApiKeyInformation(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy &UInfo, std::uint64_t TID, bool &Expired, bool &Contacted, [[maybe_unused]] bool &Suspended) { try { Types::StringPairVec QueryData; QueryData.push_back(std::make_pair("apikey", SessionToken)); std::string AlternateURIForLogging = fmt::format("/api/v1/validateApiKey?apiKey={}", Utils::SanitizeToken(SessionToken)); OpenAPIRequestGet Req(uSERVICE_SECURITY, "/api/v1/validateApiKey", QueryData, 10000, AlternateURIForLogging); Poco::JSON::Object::Ptr Response; auto StatusCode = Req.Do(Response); if (StatusCode == Poco::Net::HTTPServerResponse::HTTP_GATEWAY_TIMEOUT) { Contacted = false; return false; } Contacted = true; if (StatusCode == Poco::Net::HTTPServerResponse::HTTP_OK) { if (Response->has("tokenInfo") && Response->has("userInfo") && Response->has("expiresOn")) { UInfo.from_json(Response); Expired = false; ApiKeyCache_.update(SessionToken, ApiKeyCacheEntry{.UserInfo = UInfo, .ExpiresOn = Response->get("expiresOn")}); return true; } else { return false; } } } catch (...) { poco_error(Logger(), fmt::format("Failed to retrieve api key={} for TID={}", Utils::SanitizeToken(SessionToken), TID)); } Expired = false; return false; } bool AuthClient::IsValidApiKey(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy &UInfo, std::uint64_t TID, bool &Expired, bool &Contacted, bool &Suspended) { auto User = ApiKeyCache_.get(SessionToken); if (!User.isNull()) { if (User->ExpiresOn < Utils::Now()) { Expired = false; UInfo = User->UserInfo; return true; } ApiKeyCache_.remove(SessionToken); } return RetrieveApiKeyInformation(SessionToken, UInfo, TID, Expired, Contacted, Suspended); } } // namespace OpenWifi