From 084f19624863623bd96e899cbf432d4b2ad587c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20B=C3=A1lint=20Misius?= Date: Wed, 5 Oct 2022 10:12:17 +0200 Subject: [PATCH] Add http.getAuthToken This website API was created to enable TPTMP to prove the identity of connecting users, and while TPTMP works fine without explicit support for this from the game, it has to resort to parsing powder.pref. This is not only ugly but also likely to be disallowed by the next version of the script manager. This new script manager will probably come after 97.0, so it's okay for it to rely on a game feature that won't be available until 97.0. --- src/lua/LuaScriptInterface.cpp | 96 ++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 16 deletions(-) diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp index e7eeb98e5..829e7ea82 100644 --- a/src/lua/LuaScriptInterface.cpp +++ b/src/lua/LuaScriptInterface.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include "Format.h" #include "LuaScriptHelper.h" @@ -4015,21 +4017,82 @@ int LuaScriptInterface::event_getmodifiers(lua_State * l) class RequestHandle { +public: + enum RequestType + { + normal, + getAuthToken, + }; + +private: http::Request *request; - bool dead; + bool dead = false; + RequestType type; + + RequestHandle() = default; + + void FinishGetAuthToken(ByteString &data, int &status_out, std::vector &headers) + { + headers.clear(); + std::istringstream ss(data); + Json::Value root; + try + { + ss >> root; + auto status = root["Status"].asString(); + if (status == "OK") + { + status_out = 200; + data = root["Token"].asString(); + } + else + { + status_out = 403; + data = status; + } + } + catch (std::exception &e) + { + std::cerr << "bad auth response: " << e.what() << std::endl; + status_out = 600; + data.clear(); + } + } public: - RequestHandle(ByteString &uri, bool isPost, std::map &post_data, std::vector &headers) + static int Make(lua_State *l, const ByteString &uri, bool isPost, RequestType type, const std::map &post_data, const std::vector &headers) { - dead = false; - request = new http::Request(uri); + auto authUser = Client::Ref().GetAuthUser(); + if (type == getAuthToken && !authUser.UserID) + { + lua_pushnil(l); + lua_pushliteral(l, "not authenticated"); + return 2; + } + auto *rh = (RequestHandle *)lua_newuserdata(l, sizeof(RequestHandle)); + if (!rh) + { + return 0; + } + new(rh) RequestHandle(); + rh->type = type; + rh->request = new http::Request(uri); for (auto &header : headers) { - request->AddHeader(header); + rh->request->AddHeader(header); } if (isPost) - request->AddPostData(post_data); - request->Start(); + { + rh->request->AddPostData(post_data); + } + if (type == getAuthToken) + { + rh->request->AuthHeaders(ByteString::Build(authUser.UserID), authUser.SessionID); + } + rh->request->Start(); + luaL_newmetatable(l, "HTTPRequest"); + lua_setmetatable(l, -2); + return 1; } ~RequestHandle() @@ -4075,6 +4138,10 @@ public: if (request->CheckDone()) { data = request->Finish(&status_out, &headers); + if (type == getAuthToken && status_out == 200) + { + FinishGetAuthToken(data, status_out, headers); + } dead = true; } } @@ -4196,17 +4263,13 @@ static int http_request(lua_State *l, bool isPost) } } } - auto *rh = (RequestHandle *)lua_newuserdata(l, sizeof(RequestHandle)); - if (!rh) - { - return 0; - } - new(rh) RequestHandle(uri, isPost, post_data, headers); - luaL_newmetatable(l, "HTTPRequest"); - lua_setmetatable(l, -2); - return 1; + return RequestHandle::Make(l, uri, isPost, RequestHandle::normal, post_data, headers); } +static int http_get_auth_token(lua_State *l) +{ + return RequestHandle::Make(l, SCHEME SERVER "/ExternalAuth.api?Action=Get&Audience=" + format::URLEncode(tpt_lua_checkByteString(l, 1)), false, RequestHandle::getAuthToken, {}, {}); +} int LuaScriptInterface::http_get(lua_State * l) { @@ -4238,6 +4301,7 @@ void LuaScriptInterface::initHttpAPI() struct luaL_Reg httpMethods[] = { { "get", http_get }, { "post", http_post }, + { "getAuthToken", http_get_auth_token }, { NULL, NULL } }; luaL_register(l, NULL, httpMethods);