diff options
| author | Kowalski, Kamil <kamil.kowalski@intel.com> | 2018-01-31 13:24:59 +0100 |
|---|---|---|
| committer | Ed Tanous <ed.tanous@intel.com> | 2018-02-05 15:40:03 -0800 |
| commit | 2b7981f6e53f76c662d427ced8bd9cffc5dde695 (patch) | |
| tree | 22412d4e43c4a963e01067487c6f9d1175d5409e /include | |
| parent | 109799e512a6abcad3303dffa0505fcf2a521a1a (diff) | |
| download | bmcweb-2b7981f6e53f76c662d427ced8bd9cffc5dde695.tar.gz bmcweb-2b7981f6e53f76c662d427ced8bd9cffc5dde695.zip | |
Session and SessionCollection
New Redfish-Core nodes added (removed from redfish_v1.hpp) - Session
and SessionCollection. Tested manually on x86 VM and Wolfpass Platform.
Behavior almost identical to what was before - differences:
- SessionCollection - now only returns TIMEOUT presistence sessions, not SINGLE
- Aquiring sessions from session storage now applies timeouts
Change-Id: I68bf4fa7fa1c8371216a7d4daa30bbfb653cfa72
Signed-off-by: Kowalski, Kamil <kamil.kowalski@intel.com>
Diffstat (limited to 'include')
| -rw-r--r-- | include/persistent_data_middleware.hpp | 173 | ||||
| -rw-r--r-- | include/redfish_v1.hpp | 114 | ||||
| -rw-r--r-- | include/session_storage_singleton.hpp | 10 | ||||
| -rw-r--r-- | include/sessions.hpp | 181 | ||||
| -rw-r--r-- | include/token_authorization_middleware.hpp | 77 |
5 files changed, 233 insertions, 322 deletions
diff --git a/include/persistent_data_middleware.hpp b/include/persistent_data_middleware.hpp index b52e225..9d6195c 100644 --- a/include/persistent_data_middleware.hpp +++ b/include/persistent_data_middleware.hpp @@ -4,6 +4,7 @@ #include <pam_authenticate.hpp> #include <webassets.hpp> #include <random> +#include "session_storage_singleton.hpp" #include <crow/app.h> #include <crow/http_request.h> #include <crow/http_response.h> @@ -16,182 +17,23 @@ namespace crow { namespace PersistentData { -enum class PersistenceType { - TIMEOUT, // User session times out after a predetermined amount of time - SINGLE_REQUEST // User times out once this request is completed. -}; - -struct UserSession { - std::string unique_id; - std::string session_token; - std::string username; - std::string csrf_token; - std::chrono::time_point<std::chrono::steady_clock> last_updated; - PersistenceType persistence; -}; - -void to_json(nlohmann::json& j, const UserSession& p) { - if (p.persistence != PersistenceType::SINGLE_REQUEST) { - j = nlohmann::json{{"unique_id", p.unique_id}, - {"session_token", p.session_token}, - {"username", p.username}, - {"csrf_token", p.csrf_token}}; - } -} - -void from_json(const nlohmann::json& j, UserSession& p) { - try { - p.unique_id = j.at("unique_id").get<std::string>(); - p.session_token = j.at("session_token").get<std::string>(); - p.username = j.at("username").get<std::string>(); - p.csrf_token = j.at("csrf_token").get<std::string>(); - // For now, sessions that were persisted through a reboot get their timer - // reset. This could probably be overcome with a better understanding of - // wall clock time and steady timer time, possibly persisting values with - // wall clock time instead of steady timer, but the tradeoffs of all the - // corner cases involved are non-trivial, so this is done temporarily - p.last_updated = std::chrono::steady_clock::now(); - } catch (std::out_of_range) { - // do nothing. Session API incompatibility, leave sessions empty - } -} - -class Middleware; - -class SessionStore { - public: - const UserSession& generate_user_session( - const std::string& username, - PersistenceType persistence = PersistenceType::TIMEOUT) { - // TODO(ed) find a secure way to not generate session identifiers if - // persistence is set to SINGLE_REQUEST - static constexpr std::array<char, 62> alphanum = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', - 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', - 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; - - // entropy: 30 characters, 62 possibilities. log2(62^30) = 178 bits of - // entropy. OWASP recommends at least 60 - // https://www.owasp.org/index.php/Session_Management_Cheat_Sheet#Session_ID_Entropy - std::string session_token; - session_token.resize(20, '0'); - std::uniform_int_distribution<int> dist(0, alphanum.size() - 1); - for (int i = 0; i < session_token.size(); ++i) { - session_token[i] = alphanum[dist(rd)]; - } - // Only need csrf tokens for cookie based auth, token doesn't matter - std::string csrf_token; - csrf_token.resize(20, '0'); - for (int i = 0; i < csrf_token.size(); ++i) { - csrf_token[i] = alphanum[dist(rd)]; - } - - std::string unique_id; - unique_id.resize(10, '0'); - for (int i = 0; i < unique_id.size(); ++i) { - unique_id[i] = alphanum[dist(rd)]; - } - - const auto session_it = auth_tokens.emplace( - session_token, - std::move(UserSession{unique_id, session_token, username, csrf_token, - std::chrono::steady_clock::now(), persistence})); - const UserSession& user = (session_it).first->second; - // Only need to write to disk if session isn't about to be destroyed. - need_write_ = persistence == PersistenceType::TIMEOUT; - return user; - } - - const UserSession* login_session_by_token(const std::string& token) { - apply_session_timeouts(); - auto session_it = auth_tokens.find(token); - if (session_it == auth_tokens.end()) { - return nullptr; - } - UserSession& foo = session_it->second; - foo.last_updated = std::chrono::steady_clock::now(); - return &foo; - } - - const UserSession* get_session_by_uid(const std::string& uid) { - apply_session_timeouts(); - // TODO(Ed) this is inefficient - auto session_it = auth_tokens.begin(); - while (session_it != auth_tokens.end()) { - if (session_it->second.unique_id == uid) { - return &session_it->second; - } - session_it++; - } - return nullptr; - } - - void remove_session(const UserSession* session) { - auth_tokens.erase(session->session_token); - need_write_ = true; - } - - std::vector<const std::string*> get_unique_ids() { - std::vector<const std::string*> ret; - ret.reserve(auth_tokens.size()); - for (auto& session : auth_tokens) { - ret.push_back(&session.second.unique_id); - } - return ret; - } - - bool needs_write() { return need_write_; } - - // Persistent data middleware needs to be able to serialize our auth_tokens - // structure, which is private - friend Middleware; - - private: - void apply_session_timeouts() { - std::chrono::minutes timeout(60); - auto time_now = std::chrono::steady_clock::now(); - if (time_now - last_timeout_update > std::chrono::minutes(1)) { - last_timeout_update = time_now; - auto auth_tokens_it = auth_tokens.begin(); - while (auth_tokens_it != auth_tokens.end()) { - if (time_now - auth_tokens_it->second.last_updated >= timeout) { - auth_tokens_it = auth_tokens.erase(auth_tokens_it); - need_write_ = true; - } else { - auth_tokens_it++; - } - } - } - } - std::chrono::time_point<std::chrono::steady_clock> last_timeout_update; - boost::container::flat_map<std::string, UserSession> auth_tokens; - std::random_device rd; - bool need_write_{false}; -}; - class Middleware { // todo(ed) should read this from a fixed location somewhere, not CWD static constexpr const char* filename = "bmcweb_persistent_data.json"; int json_revision = 1; public: - struct context { - SessionStore* sessions; - }; + struct context {}; Middleware() { read_data(); } ~Middleware() { - if (sessions.needs_write()) { + if (PersistentData::session_store->needs_write()) { write_data(); } } - void before_handle(crow::request& req, response& res, context& ctx) { - ctx.sessions = &sessions; - } + void before_handle(crow::request& req, response& res, context& ctx) {} void after_handle(request& req, response& res, context& ctx) {} @@ -206,8 +48,8 @@ class Middleware { auto data = nlohmann::json::parse(persistent_file, nullptr, false); if (!data.is_discarded()) { file_revision = data.value("revision", 0); - sessions.auth_tokens = - data.value("sessions", decltype(sessions.auth_tokens)()); + PersistentData::session_store->auth_tokens = + data.value("sessions", decltype(session_store->auth_tokens)()); system_uuid = data.value("system_uuid", ""); } } @@ -229,13 +71,12 @@ class Middleware { void write_data() { std::ofstream persistent_file(filename); nlohmann::json data; - data["sessions"] = sessions.auth_tokens; + data["sessions"] = PersistentData::session_store->auth_tokens; data["system_uuid"] = system_uuid; data["revision"] = json_revision; persistent_file << data; } - SessionStore sessions; std::string system_uuid; }; diff --git a/include/redfish_v1.hpp b/include/redfish_v1.hpp index 1a5ee74..3aecae0 100644 --- a/include/redfish_v1.hpp +++ b/include/redfish_v1.hpp @@ -168,9 +168,8 @@ void request_routes(Crow<Middlewares...>& app) { for (int user_index = 0; user_index < users.size(); user_index++) { member_array.push_back( - {{"@odata.id", - "/redfish/v1/AccountService/Accounts/" + - std::to_string(user_index)}}); + {{"@odata.id", "/redfish/v1/AccountService/Accounts/" + + std::to_string(user_index)}}); } res.json_value["Members"] = member_array; } @@ -222,110 +221,6 @@ void request_routes(Crow<Middlewares...>& app) { res.end(); }); - CROW_ROUTE(app, "/redfish/v1/SessionService/Sessions/") - .methods("POST"_method, "GET"_method)([&](const crow::request& req, - crow::response& res) { - auto& session_store = - app.template get_middleware<PersistentData::Middleware>().sessions; - if (req.method == "POST"_method) { - // call with exceptions disabled - auto login_credentials = - nlohmann::json::parse(req.body, nullptr, false); - if (login_credentials.is_discarded()) { - res.code = 400; - res.end(); - return; - } - // check for username/password in the root object - auto user_it = login_credentials.find("UserName"); - auto pass_it = login_credentials.find("Password"); - if (user_it == login_credentials.end() || - pass_it == login_credentials.end()) { - res.code = 400; - res.end(); - return; - } - - std::string username = user_it->get<const std::string>(); - std::string password = pass_it->get<const std::string>(); - if (username.empty() || password.empty()) { - res.code = 400; - res.end(); - return; - } - - if (!pam_authenticate_user(username, password)) { - res.code = 401; - res.end(); - return; - } - auto session = session_store.generate_user_session(username); - res.code = 200; - res.add_header("X-Auth-Token", session.session_token); - res.json_value = { - {"@odata.context", "/redfish/v1/$metadata#Session"}, - {"@odata.id", - "/redfish/v1/SessionService/Sessions/" + session.unique_id}, - {"@odata.type", "#Session.v1_0_3.Session"}, - {"Id", session.unique_id}, - {"Name", "User Session"}, - {"Description", "Manager User Session"}, - {"UserName", username}}; - } else { // assume get - std::vector<const std::string*> session_ids = - session_store.get_unique_ids(); - res.json_value = { - {"@odata.context", - "/redfish/v1/$metadata#SessionCollection.SessionCollection"}, - {"@odata.id", "/redfish/v1/SessionService/Sessions"}, - {"@odata.type", "#SessionCollection.SessionCollection"}, - {"Name", "Session Collection"}, - {"Description", "Session Collection"}, - {"Members@odata.count", session_ids.size()} - - }; - nlohmann::json member_array = nlohmann::json::array(); - for (auto session_uid : session_ids) { - member_array.push_back( - {{"@odata.id", - "/redfish/v1/SessionService/Sessions/" + *session_uid}}); - } - res.json_value["Members"] = member_array; - } - res.end(); - }); - - CROW_ROUTE(app, "/redfish/v1/SessionService/Sessions/<str>/") - .methods("GET"_method, "DELETE"_method)([&]( - const crow::request& req, crow::response& res, - const std::string& session_id) { - auto& session_store = - app.template get_middleware<PersistentData::Middleware>().sessions; - // TODO(Ed) this is inefficient - auto session = session_store.get_session_by_uid(session_id); - - if (session == nullptr) { - res.code = 404; - res.end(); - return; - } - if (req.method == "DELETE"_method) { - session_store.remove_session(session); - res.code = 200; - } else { // assume get - res.json_value = { - {"@odata.context", "/redfish/v1/$metadata#Session.Session"}, - {"@odata.id", - "/redfish/v1/SessionService/Sessions/" + session->unique_id}, - {"@odata.type", "#Session.v1_0_3.Session"}, - {"Id", session->unique_id}, - {"Name", "User Session"}, - {"Description", "Manager User Session"}, - {"UserName", session->username}}; - } - res.end(); - }); - CROW_ROUTE(app, "/redfish/v1/Managers/") .methods("GET"_method)( [&](const crow::request& req, crow::response& res) { @@ -365,9 +260,8 @@ void request_routes(Crow<Middlewares...>& app) { {"Id", "openbmc"}, {"Name", "OpenBmc Manager"}, {"Description", "Baseboard Management Controller"}, - {"UUID", - app.template get_middleware<PersistentData::Middleware>() - .system_uuid}, + {"UUID", app.template get_middleware<PersistentData::Middleware>() + .system_uuid}, {"Model", "OpenBmc"}, // TODO(ed), get model {"DateTime", time_buffer.data()}, {"Status", diff --git a/include/session_storage_singleton.hpp b/include/session_storage_singleton.hpp new file mode 100644 index 0000000..6ff8a0e --- /dev/null +++ b/include/session_storage_singleton.hpp @@ -0,0 +1,10 @@ +#pragma once +#include "sessions.hpp" + +namespace crow { +namespace PersistentData { + +static std::shared_ptr<SessionStore> session_store; + +} // namespace PersistentData +} // namespace crow diff --git a/include/sessions.hpp b/include/sessions.hpp new file mode 100644 index 0000000..6d4ab4d --- /dev/null +++ b/include/sessions.hpp @@ -0,0 +1,181 @@ +#pragma once + +#include <nlohmann/json.hpp> +#include <pam_authenticate.hpp> +#include <webassets.hpp> +#include <random> +#include <crow/app.h> +#include <crow/http_request.h> +#include <crow/http_response.h> +#include <boost/container/flat_map.hpp> +#include <boost/uuid/uuid.hpp> +#include <boost/uuid/uuid_generators.hpp> +#include <boost/uuid/uuid_io.hpp> + +namespace crow { + +namespace PersistentData { + +enum class PersistenceType { + TIMEOUT, // User session times out after a predetermined amount of time + SINGLE_REQUEST // User times out once this request is completed. +}; + +struct UserSession { + std::string unique_id; + std::string session_token; + std::string username; + std::string csrf_token; + std::chrono::time_point<std::chrono::steady_clock> last_updated; + PersistenceType persistence; +}; + +void to_json(nlohmann::json& j, const UserSession& p) { + if (p.persistence != PersistenceType::SINGLE_REQUEST) { + j = nlohmann::json{{"unique_id", p.unique_id}, + {"session_token", p.session_token}, + {"username", p.username}, + {"csrf_token", p.csrf_token}}; + } +} + +void from_json(const nlohmann::json& j, UserSession& p) { + try { + p.unique_id = j.at("unique_id").get<std::string>(); + p.session_token = j.at("session_token").get<std::string>(); + p.username = j.at("username").get<std::string>(); + p.csrf_token = j.at("csrf_token").get<std::string>(); + // For now, sessions that were persisted through a reboot get their timer + // reset. This could probably be overcome with a better understanding of + // wall clock time and steady timer time, possibly persisting values with + // wall clock time instead of steady timer, but the tradeoffs of all the + // corner cases involved are non-trivial, so this is done temporarily + p.last_updated = std::chrono::steady_clock::now(); + } catch (std::out_of_range) { + // do nothing. Session API incompatibility, leave sessions empty + } +} + +class Middleware; + +class SessionStore { + public: + const UserSession& generate_user_session( + const std::string& username, + PersistenceType persistence = PersistenceType::TIMEOUT) { + // TODO(ed) find a secure way to not generate session identifiers if + // persistence is set to SINGLE_REQUEST + static constexpr std::array<char, 62> alphanum = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; + + // entropy: 30 characters, 62 possibilities. log2(62^30) = 178 bits of + // entropy. OWASP recommends at least 60 + // https://www.owasp.org/index.php/Session_Management_Cheat_Sheet#Session_ID_Entropy + std::string session_token; + session_token.resize(20, '0'); + std::uniform_int_distribution<int> dist(0, alphanum.size() - 1); + for (int i = 0; i < session_token.size(); ++i) { + session_token[i] = alphanum[dist(rd)]; + } + // Only need csrf tokens for cookie based auth, token doesn't matter + std::string csrf_token; + csrf_token.resize(20, '0'); + for (int i = 0; i < csrf_token.size(); ++i) { + csrf_token[i] = alphanum[dist(rd)]; + } + + std::string unique_id; + unique_id.resize(10, '0'); + for (int i = 0; i < unique_id.size(); ++i) { + unique_id[i] = alphanum[dist(rd)]; + } + + const auto session_it = auth_tokens.emplace( + session_token, + std::move(UserSession{unique_id, session_token, username, csrf_token, + std::chrono::steady_clock::now(), persistence})); + const UserSession& user = (session_it).first->second; + // Only need to write to disk if session isn't about to be destroyed. + need_write_ = persistence == PersistenceType::TIMEOUT; + return user; + } + + const UserSession* login_session_by_token(const std::string& token) { + apply_session_timeouts(); + auto session_it = auth_tokens.find(token); + if (session_it == auth_tokens.end()) { + return nullptr; + } + UserSession& foo = session_it->second; + foo.last_updated = std::chrono::steady_clock::now(); + return &foo; + } + + const UserSession* get_session_by_uid(const std::string& uid) { + apply_session_timeouts(); + // TODO(Ed) this is inefficient + auto session_it = auth_tokens.begin(); + while (session_it != auth_tokens.end()) { + if (session_it->second.unique_id == uid) { + return &session_it->second; + } + session_it++; + } + return nullptr; + } + + void remove_session(const UserSession* session) { + auth_tokens.erase(session->session_token); + need_write_ = true; + } + + std::vector<const std::string*> get_unique_ids( + bool getAll = true, + const PersistenceType& type = PersistenceType::SINGLE_REQUEST) { + apply_session_timeouts(); + + std::vector<const std::string*> ret; + ret.reserve(auth_tokens.size()); + for (auto& session : auth_tokens) { + if (getAll || type == session.second.persistence) { + ret.push_back(&session.second.unique_id); + } + } + return ret; + } + + bool needs_write() { return need_write_; } + + // Persistent data middleware needs to be able to serialize our auth_tokens + // structure, which is private + friend Middleware; + + private: + void apply_session_timeouts() { + std::chrono::minutes timeout(60); + auto time_now = std::chrono::steady_clock::now(); + if (time_now - last_timeout_update > std::chrono::minutes(1)) { + last_timeout_update = time_now; + auto auth_tokens_it = auth_tokens.begin(); + while (auth_tokens_it != auth_tokens.end()) { + if (time_now - auth_tokens_it->second.last_updated >= timeout) { + auth_tokens_it = auth_tokens.erase(auth_tokens_it); + need_write_ = true; + } else { + auth_tokens_it++; + } + } + } + } + std::chrono::time_point<std::chrono::steady_clock> last_timeout_update; + boost::container::flat_map<std::string, UserSession> auth_tokens; + std::random_device rd; + bool need_write_{false}; +}; + +} // namespaec PersistentData +} // namespace crow diff --git a/include/token_authorization_middleware.hpp b/include/token_authorization_middleware.hpp index 8099020..7497b43 100644 --- a/include/token_authorization_middleware.hpp +++ b/include/token_authorization_middleware.hpp @@ -20,23 +20,20 @@ class Middleware { struct context { const crow::PersistentData::UserSession* session; }; - template <typename AllContext> - void before_handle(crow::request& req, response& res, context& ctx, - AllContext& allctx) { - auto& sessions = - allctx.template get<crow::PersistentData::Middleware>().sessions; + + void before_handle(crow::request& req, response& res, context& ctx) { std::string auth_header = req.get_header_value("Authorization"); if (auth_header != "") { // Reject any kind of auth other than basic or token if (boost::starts_with(auth_header, "Basic ")) { - ctx.session = perform_basic_auth(auth_header, sessions); + ctx.session = perform_basic_auth(auth_header); } else if (boost::starts_with(auth_header, "Token ")) { - ctx.session = perform_token_auth(auth_header, sessions); + ctx.session = perform_token_auth(auth_header); } } else if (req.headers.count("X-Auth-Token") == 1) { - ctx.session = perform_xtoken_auth(req, sessions); + ctx.session = perform_xtoken_auth(req); } else if (req.headers.count("Cookie") == 1) { - ctx.session = perform_cookie_auth(req, sessions); + ctx.session = perform_cookie_auth(req); } if (ctx.session == nullptr && !is_on_whitelist(req)) { @@ -61,17 +58,13 @@ class Middleware { if (ctx.session != nullptr && ctx.session->persistence == crow::PersistentData::PersistenceType::SINGLE_REQUEST) { - auto& session_store = - allctx.template get<crow::PersistentData::Middleware>().sessions; - - session_store->remove_session(ctx.session); + PersistentData::session_store->remove_session(ctx.session); } } private: const crow::PersistentData::UserSession* perform_basic_auth( - const std::string& auth_header, - crow::PersistentData::SessionStore* sessions) const { + const std::string& auth_header) const { CROW_LOG_DEBUG << "[AuthMiddleware] Basic authentication"; std::string auth_data; @@ -103,33 +96,30 @@ class Middleware { // needed. // This whole flow needs to be revisited anyway, as we can't be // calling directly into pam for every request - return &(sessions->generate_user_session( + return &(PersistentData::session_store->generate_user_session( user, crow::PersistentData::PersistenceType::SINGLE_REQUEST)); } const crow::PersistentData::UserSession* perform_token_auth( - const std::string& auth_header, - crow::PersistentData::SessionStore* sessions) const { + const std::string& auth_header) const { CROW_LOG_DEBUG << "[AuthMiddleware] Token authentication"; std::string token = auth_header.substr(strlen("Token ")); - auto session = sessions->login_session_by_token(token); + auto session = PersistentData::session_store->login_session_by_token(token); return session; } const crow::PersistentData::UserSession* perform_xtoken_auth( - const crow::request& req, - crow::PersistentData::SessionStore* sessions) const { + const crow::request& req) const { CROW_LOG_DEBUG << "[AuthMiddleware] X-Auth-Token authentication"; auto& token = req.get_header_value("X-Auth-Token"); - auto session = sessions->login_session_by_token(token); + auto session = PersistentData::session_store->login_session_by_token(token); return session; } const crow::PersistentData::UserSession* perform_cookie_auth( - const crow::request& req, - crow::PersistentData::SessionStore* sessions) const { + const crow::request& req) const { CROW_LOG_DEBUG << "[AuthMiddleware] Cookie authentication"; auto& cookie_value = req.get_header_value("Cookie"); @@ -147,7 +137,7 @@ class Middleware { cookie_value.substr(start_index, end_index - start_index); const crow::PersistentData::UserSession* session = - sessions->login_session_by_token(auth_key); + PersistentData::session_store->login_session_by_token(auth_key); if (session == nullptr) { return nullptr; } @@ -266,10 +256,8 @@ void request_routes(Crow<Middlewares...>& app) { if (!pam_authenticate_user(username, password)) { res.code = res.code = static_cast<int>(HttpRespCode::UNAUTHORIZED); } else { - auto& context = - app.template get_context<PersistentData::Middleware>(req); - auto& session_store = context.sessions; - auto& session = session_store->generate_user_session(username); + auto& session = + PersistentData::session_store->generate_user_session(username); if (looks_like_ibm) { // IBM requires a very specific login structure, and doesn't @@ -279,9 +267,8 @@ void request_routes(Crow<Middlewares...>& app) { {"message", "200 OK"}, {"status", "ok"}}; res.add_header("Set-Cookie", "XSRF-TOKEN=" + session.csrf_token); - res.add_header( - "Set-Cookie", - "SESSION=" + session.session_token + "; Secure; HttpOnly"); + res.add_header("Set-Cookie", "SESSION=" + session.session_token + + "; Secure; HttpOnly"); res.write(ret.dump()); } else { @@ -300,21 +287,19 @@ void request_routes(Crow<Middlewares...>& app) { }); CROW_ROUTE(app, "/logout") - .methods( - "POST"_method)([&](const crow::request& req, crow::response& res) { - auto& session_store = - app.template get_context<PersistentData::Middleware>(req).sessions; - auto& session = - app.template get_context<TokenAuthorization::Middleware>(req) - .session; - if (session != nullptr) { - session_store->remove_session(session); - } - res.code = static_cast<int>(HttpRespCode::OK); - res.end(); - return; + .methods("POST"_method)( + [&](const crow::request& req, crow::response& res) { + auto& session = + app.template get_context<TokenAuthorization::Middleware>(req) + .session; + if (session != nullptr) { + PersistentData::session_store->remove_session(session); + } + res.code = static_cast<int>(HttpRespCode::OK); + res.end(); + return; - }); + }); } } // namespaec TokenAuthorization } // namespace crow |

