// Copyright Epic Games, Inc. All Rights Reserved. #include "zenhttp/auth/authservice.h" #include #include #include #include ZEN_THIRD_PARTY_INCLUDES_START #include ZEN_THIRD_PARTY_INCLUDES_END namespace zen { using namespace std::literals; HttpAuthService::HttpAuthService(AuthMgr& AuthMgr) : m_AuthMgr(AuthMgr) { m_Router.RegisterRoute( "oidc/refreshtoken", [this](HttpRouterRequest& RouterRequest) { HttpServerRequest& ServerRequest = RouterRequest.ServerRequest(); // The refresh-token endpoint is how the local Unreal Editor / zen CLI // hands off a refresh token obtained via an interactive flow. There // is no legitimate reason for it to be reachable from the network: a // remote caller that can reach it can evict the cached token (DoS) // or — with a valid same-provider token — substitute credentials used // by GetOpenIdAccessToken. Require the origin to be the local // machine; any configured password filter still runs in front. if (!ServerRequest.IsLocalMachineRequest()) { ZEN_WARN("rejecting non-local POST to /auth/oidc/refreshtoken"); return ServerRequest.WriteResponse(HttpResponseCode::Forbidden); } 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(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(); std::string ProviderName = TokenInfo["ProviderName"].string_value(); if (ProviderName.empty()) { ProviderName = "Default"sv; } const bool Ok = m_AuthMgr.AddOpenIdToken(AuthMgr::AddOpenIdTokenParams{.ProviderName = ProviderName, .RefreshToken = RefreshToken}); if (Ok) { ServerRequest.WriteResponse(HttpResponseCode::OK); } else { CbObjectWriter Response; Response << "Result"sv << false; Response << "Error"sv << "Invalid token"sv; ServerRequest.WriteResponse(HttpResponseCode::BadRequest, Response.Save()); } }, HttpVerb::kPost); } HttpAuthService::~HttpAuthService() { } const char* HttpAuthService::BaseUri() const { return "/auth/"; } void HttpAuthService::HandleRequest(zen::HttpServerRequest& Request) { m_Router.HandleRequest(Request); } } // namespace zen