diff options
| author | Per Larsson <[email protected]> | 2022-01-25 18:36:41 +0100 |
|---|---|---|
| committer | Per Larsson <[email protected]> | 2022-01-25 18:36:41 +0100 |
| commit | 060c3ed4b49c6341d1a917ec728d26bda7e41494 (patch) | |
| tree | 054b147827833efd715a08f08f85d7d2e25c609c | |
| parent | Fixed missing object in project oplog response. (diff) | |
| download | zen-060c3ed4b49c6341d1a917ec728d26bda7e41494.tar.xz zen-060c3ed4b49c6341d1a917ec728d26bda7e41494.zip | |
Added auth manager with support for OIDC providers.
| -rw-r--r-- | zenserver/auth/authmgr.cpp | 72 | ||||
| -rw-r--r-- | zenserver/auth/authmgr.h | 36 | ||||
| -rw-r--r-- | zenserver/auth/authservice.cpp | 33 | ||||
| -rw-r--r-- | zenserver/auth/authservice.h | 5 | ||||
| -rw-r--r-- | zenserver/config.cpp | 5 | ||||
| -rw-r--r-- | zenserver/zenserver.cpp | 8 |
6 files changed, 155 insertions, 4 deletions
diff --git a/zenserver/auth/authmgr.cpp b/zenserver/auth/authmgr.cpp new file mode 100644 index 000000000..af579d950 --- /dev/null +++ b/zenserver/auth/authmgr.cpp @@ -0,0 +1,72 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include <auth/authmgr.h> +#include <zencore/logging.h> + +#include <chrono> +#include <condition_variable> +#include <shared_mutex> +#include <thread> +#include <unordered_map> + +namespace zen { + +class AuthMgrImpl final : public AuthMgr +{ +public: + AuthMgrImpl(const AuthConfig& Config) : m_Log(logging::Get("auth")) + { + ZEN_UNUSED(Config); + } + + virtual ~AuthMgrImpl() {} + + virtual void AddOpenIdProvider(const AddOpenIdProviderParams& Params) final + { + std::string NewProviderName = std::string(Params.Name); + + OpenIdProvider* NewProvider = nullptr; + + { + std::unique_lock _(m_ProviderMutex); + + if (m_OpenIdProviders.contains(NewProviderName)) + { + return; + } + + auto InsertResult = m_OpenIdProviders.emplace(NewProviderName, std::make_unique<OpenIdProvider>()); + NewProvider = InsertResult.first->second.get(); + } + + NewProvider->Name = std::string(Params.Name); + NewProvider->Url = std::string(Params.Url); + NewProvider->ClientId = std::string(Params.ClientId); + + ZEN_INFO("added OpenID provider '{} - {}'", Params.Name, Params.Url); + } + +private: + struct OpenIdProvider + { + std::string Name; + std::string Url; + std::string ClientId; + }; + + using OpenIdProviderMap = std::unordered_map<std::string, std::unique_ptr<OpenIdProvider>>; + + spdlog::logger& Log() { return m_Log; } + + spdlog::logger& m_Log; + std::mutex m_ProviderMutex; + OpenIdProviderMap m_OpenIdProviders; +}; + +std::unique_ptr<AuthMgr> +MakeAuthMgr(const AuthConfig& Config) +{ + return std::make_unique<AuthMgrImpl>(Config); +} + +} // namespace zen diff --git a/zenserver/auth/authmgr.h b/zenserver/auth/authmgr.h new file mode 100644 index 000000000..33bd15ee9 --- /dev/null +++ b/zenserver/auth/authmgr.h @@ -0,0 +1,36 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include <zencore/string.h> + +#include <filesystem> +#include <memory> + +namespace zen { + +class AuthMgr +{ +public: + virtual ~AuthMgr() = default; + + struct AddOpenIdProviderParams + { + std::string_view Name; + std::string_view Url; + std::string_view ClientId; + }; + + virtual void AddOpenIdProvider(const AddOpenIdProviderParams& Params) = 0; + + struct AddOpenIdTokenParams + { + }; +}; + +struct AuthConfig +{ + std::filesystem::path RootDirectory; +}; + +std::unique_ptr<AuthMgr> MakeAuthMgr(const AuthConfig& Config); + +} // namespace zen diff --git a/zenserver/auth/authservice.cpp b/zenserver/auth/authservice.cpp index c6def15b4..8200b9c9b 100644 --- a/zenserver/auth/authservice.cpp +++ b/zenserver/auth/authservice.cpp @@ -1,18 +1,49 @@ // Copyright Epic Games, Inc. All Rights Reserved. #include <auth/authservice.h> +#include <auth/authmgr.h> + +#include <zencore/compactbinarybuilder.h> #include <zencore/string.h> +#include <json11.hpp> + namespace zen { using namespace std::literals; -HttpAuthService::HttpAuthService() +HttpAuthService::HttpAuthService(AuthMgr& AuthMgr) : m_AuthMgr(AuthMgr) { m_Router.RegisterRoute( "token", [this](HttpRouterRequest& RouterRequest) { HttpServerRequest& ServerRequest = RouterRequest.ServerRequest(); + + const HttpContentType ContentType = ServerRequest.RequestContentType(); + + if ((ContentType == HttpContentType::kUnknownContentType || ContentType == HttpContentType::kJSON) == false) + { + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest); + } + + const IoBuffer Body = ServerRequest.ReadPayload(); + + std::string JsonText(reinterpret_cast<const char*>(Body.GetData()), Body.GetSize()); + std::string JsonError; + json11::Json TokenInfo = json11::Json::parse(JsonText, JsonError); + + if (!JsonError.empty()) + { + CbObjectWriter Response; + Response << "Result"sv << false; + Response << "Error"sv << JsonError; + + return ServerRequest.WriteResponse(HttpResponseCode::BadRequest, Response.Save()); + } + + const std::string RefreshToken = TokenInfo["RefreshToken"].string_value(); + const std::string AccessToken = TokenInfo["AccessToken"].string_value(); + ServerRequest.WriteResponse(HttpResponseCode::OK); }, HttpVerb::kPost); diff --git a/zenserver/auth/authservice.h b/zenserver/auth/authservice.h index 30b2b5864..64b86e21f 100644 --- a/zenserver/auth/authservice.h +++ b/zenserver/auth/authservice.h @@ -6,16 +6,19 @@ namespace zen { +class AuthMgr; + class HttpAuthService final : public zen::HttpService { public: - HttpAuthService(); + HttpAuthService(AuthMgr& AuthMgr); virtual ~HttpAuthService(); virtual const char* BaseUri() const override; virtual void HandleRequest(zen::HttpServerRequest& Request) override; private: + AuthMgr& m_AuthMgr; HttpRequestRouter m_Router; }; diff --git a/zenserver/config.cpp b/zenserver/config.cpp index 4afe012dd..a4439d914 100644 --- a/zenserver/config.cpp +++ b/zenserver/config.cpp @@ -91,6 +91,8 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) const char* DefaultHttp = "asio"; #endif + std::string DataDir; + cxxopts::Options options("zenserver", "Zen Server"); options.add_options()("dedicated", "Enable dedicated server mode", @@ -99,7 +101,7 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) options.add_options()("help", "Show command line help"); options.add_options()("t, test", "Enable test mode", cxxopts::value<bool>(ServerOptions.IsTest)->default_value("false")); options.add_options()("log-id", "Specify id for adding context to log output", cxxopts::value<std::string>(ServerOptions.LogId)); - options.add_options()("data-dir", "Specify persistence root", cxxopts::value<std::filesystem::path>(ServerOptions.DataDir)); + options.add_options()("data-dir", "Specify persistence root", cxxopts::value<std::string>(DataDir)); options.add_options()("content-dir", "Frontend content directory", cxxopts::value<std::filesystem::path>(ServerOptions.ContentDir)); options.add_options()("abslog", "Path to log file", cxxopts::value<std::filesystem::path>(ServerOptions.AbsLogFile)); options.add_options()("config", "Path to Lua config file", cxxopts::value<std::filesystem::path>(ServerOptions.ConfigFile)); @@ -313,6 +315,7 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) try { auto result = options.parse(argc, argv); + ServerOptions.DataDir = DataDir; if (result.count("help")) { diff --git a/zenserver/zenserver.cpp b/zenserver/zenserver.cpp index b8648c8ee..524207921 100644 --- a/zenserver/zenserver.cpp +++ b/zenserver/zenserver.cpp @@ -99,6 +99,7 @@ ZEN_THIRD_PARTY_INCLUDES_END // #include "admin/admin.h" +#include "auth/authmgr.h" #include "auth/authservice.h" #include "cache/structuredcache.h" #include "cache/structuredcachestore.h" @@ -203,9 +204,13 @@ public: m_Http = zen::CreateHttpServer(ServerOptions.HttpServerClass); m_Http->Initialize(ServerOptions.BasePort); - m_AuthService = std::make_unique<zen::HttpAuthService>(); + m_AuthMgr = MakeAuthMgr({.RootDirectory = m_DataRoot / "auth"}); + m_AuthService = std::make_unique<zen::HttpAuthService>(*m_AuthMgr); m_Http->RegisterService(*m_AuthService); + m_AuthMgr->AddOpenIdProvider( + {.Name = "Okta"sv, .Url = "https://epicgames.okta.com/oauth2/auso645ojjWVdRI3d0x7"sv, .ClientId = "0oapq1knoglGFqQvr0x7"sv}); + m_Http->RegisterService(m_HealthService); m_Http->RegisterService(m_StatsService); m_Http->RegisterService(m_StatusService); @@ -527,6 +532,7 @@ private: } zen::Ref<zen::HttpServer> m_Http; + std::unique_ptr<zen::AuthMgr> m_AuthMgr; std::unique_ptr<zen::HttpAuthService> m_AuthService; zen::HttpStatusService m_StatusService; zen::HttpStatsService m_StatsService; |