summaryrefslogtreecommitdiff
path: root/include/token_authorization_middleware.hpp
diff options
context:
space:
mode:
authorEd Tanous <ed.tanous@intel.com>2018-05-23 01:27:24 +0300
committerEd Tanous <ed.tanous@intel.com>2018-07-27 01:54:37 +0300
commit55c7b7a2e58779580f33046d2dd8649243776700 (patch)
treeeed2d032dff3e18c4a8d4778e8f52ae5864620ee /include/token_authorization_middleware.hpp
parent1752c9657b56a6e1950d8725f44f4298c9872c63 (diff)
downloadbmcweb-55c7b7a2e58779580f33046d2dd8649243776700.tar.xz
Move over to upstream c++ style
This patchset moves bmcweb over to the upstream style naming conventions for variables, classes, and functions, as well as imposes the latest clang-format file. This changeset was mostly built automatically by the included .clang-tidy file, which has the ability to autoformat and auto rename variables. At some point in the future I would like to see this in greater use, but for now, we will impose it on bmcweb, and see how it goes. Tested: Code still compiles, and appears to run, although other issues are possible and likely. Change-Id: If422a2e36df924e897736b3feffa89f411d9dac1 Signed-off-by: Ed Tanous <ed.tanous@intel.com>
Diffstat (limited to 'include/token_authorization_middleware.hpp')
-rw-r--r--include/token_authorization_middleware.hpp259
1 files changed, 127 insertions, 132 deletions
diff --git a/include/token_authorization_middleware.hpp b/include/token_authorization_middleware.hpp
index f151e4ff63..fcc86386fa 100644
--- a/include/token_authorization_middleware.hpp
+++ b/include/token_authorization_middleware.hpp
@@ -12,49 +12,49 @@
namespace crow {
-namespace TokenAuthorization {
+namespace token_authorization {
class Middleware {
public:
- struct context {
- std::shared_ptr<crow::PersistentData::UserSession> session;
+ struct Context {
+ std::shared_ptr<crow::persistent_data::UserSession> session;
};
- void before_handle(crow::request& req, response& res, context& ctx) {
- if (is_on_whitelist(req)) {
+ void beforeHandle(crow::Request& req, Response& res, Context& ctx) {
+ if (isOnWhitelist(req)) {
return;
}
- ctx.session = perform_xtoken_auth(req);
+ ctx.session = performXtokenAuth(req);
if (ctx.session == nullptr) {
- ctx.session = perform_cookie_auth(req);
+ ctx.session = performCookieAuth(req);
}
if (ctx.session == nullptr) {
- boost::string_view auth_header = req.get_header_value("Authorization");
- if (!auth_header.empty()) {
+ boost::string_view authHeader = req.getHeaderValue("Authorization");
+ if (!authHeader.empty()) {
// Reject any kind of auth other than basic or token
- if (boost::starts_with(auth_header, "Token ")) {
- ctx.session = perform_token_auth(auth_header);
- } else if (boost::starts_with(auth_header, "Basic ")) {
- ctx.session = perform_basic_auth(auth_header);
+ if (boost::starts_with(authHeader, "Token ")) {
+ ctx.session = performTokenAuth(authHeader);
+ } else if (boost::starts_with(authHeader, "Basic ")) {
+ ctx.session = performBasicAuth(authHeader);
}
}
}
if (ctx.session == nullptr) {
- CROW_LOG_WARNING << "[AuthMiddleware] authorization failed";
+ BMCWEB_LOG_WARNING << "[AuthMiddleware] authorization failed";
// If it's a browser connecting, don't send the HTTP authenticate header,
// to avoid possible CSRF attacks with basic auth
- if (http_helpers::request_prefers_html(req)) {
+ if (http_helpers::requestPrefersHtml(req)) {
res.result(boost::beast::http::status::temporary_redirect);
- res.add_header("Location", "/#/login");
+ res.addHeader("Location", "/#/login");
} else {
res.result(boost::beast::http::status::unauthorized);
// only send the WWW-authenticate header if this isn't a xhr from the
// browser. most scripts,
- if (req.get_header_value("User-Agent").empty()) {
- res.add_header("WWW-Authenticate", "Basic");
+ if (req.getHeaderValue("User-Agent").empty()) {
+ res.addHeader("WWW-Authenticate", "Basic");
}
}
@@ -62,124 +62,122 @@ class Middleware {
return;
}
- // TODO get user privileges here and propagate it via MW context
+ // TODO get user privileges here and propagate it via MW Context
// else let the request continue unharmed
}
template <typename AllContext>
- void after_handle(request& req, response& res, context& ctx,
- AllContext& allctx) {
+ void afterHandle(Request& req, Response& res, Context& ctx,
+ AllContext& allctx) {
// TODO(ed) THis should really be handled by the persistent data
// middleware, but because it is upstream, it doesn't have access to the
// session information. Should the data middleware persist the current
// user session?
if (ctx.session != nullptr &&
ctx.session->persistence ==
- crow::PersistentData::PersistenceType::SINGLE_REQUEST) {
- PersistentData::SessionStore::getInstance().remove_session(ctx.session);
+ crow::persistent_data::PersistenceType::SINGLE_REQUEST) {
+ persistent_data::SessionStore::getInstance().removeSession(ctx.session);
}
}
private:
- const std::shared_ptr<crow::PersistentData::UserSession> perform_basic_auth(
+ const std::shared_ptr<crow::persistent_data::UserSession> performBasicAuth(
boost::string_view auth_header) const {
- CROW_LOG_DEBUG << "[AuthMiddleware] Basic authentication";
+ BMCWEB_LOG_DEBUG << "[AuthMiddleware] Basic authentication";
- std::string auth_data;
+ std::string authData;
boost::string_view param = auth_header.substr(strlen("Basic "));
- if (!crow::utility::base64_decode(param, auth_data)) {
+ if (!crow::utility::base64Decode(param, authData)) {
return nullptr;
}
- std::size_t separator = auth_data.find(':');
+ std::size_t separator = authData.find(':');
if (separator == std::string::npos) {
return nullptr;
}
- std::string user = auth_data.substr(0, separator);
+ std::string user = authData.substr(0, separator);
separator += 1;
- if (separator > auth_data.size()) {
+ if (separator > authData.size()) {
return nullptr;
}
- std::string pass = auth_data.substr(separator);
+ std::string pass = authData.substr(separator);
- CROW_LOG_DEBUG << "[AuthMiddleware] Authenticating user: " << user;
+ BMCWEB_LOG_DEBUG << "[AuthMiddleware] Authenticating user: " << user;
- if (!pam_authenticate_user(user, pass)) {
+ if (!pamAuthenticateUser(user, pass)) {
return nullptr;
}
- // TODO(ed) generate_user_session is a little expensive for basic
+ // TODO(ed) generateUserSession is a little expensive for basic
// auth, as it generates some random identifiers that will never be
// used. This should have a "fast" path for when user tokens aren't
// needed.
// This whole flow needs to be revisited anyway, as we can't be
// calling directly into pam for every request
- return PersistentData::SessionStore::getInstance().generate_user_session(
- user, crow::PersistentData::PersistenceType::SINGLE_REQUEST);
+ return persistent_data::SessionStore::getInstance().generateUserSession(
+ user, crow::persistent_data::PersistenceType::SINGLE_REQUEST);
}
- const std::shared_ptr<crow::PersistentData::UserSession> perform_token_auth(
+ const std::shared_ptr<crow::persistent_data::UserSession> performTokenAuth(
boost::string_view auth_header) const {
- CROW_LOG_DEBUG << "[AuthMiddleware] Token authentication";
+ BMCWEB_LOG_DEBUG << "[AuthMiddleware] Token authentication";
boost::string_view token = auth_header.substr(strlen("Token "));
auto session =
- PersistentData::SessionStore::getInstance().login_session_by_token(
- token);
+ persistent_data::SessionStore::getInstance().loginSessionByToken(token);
return session;
}
- const std::shared_ptr<crow::PersistentData::UserSession> perform_xtoken_auth(
- const crow::request& req) const {
- CROW_LOG_DEBUG << "[AuthMiddleware] X-Auth-Token authentication";
+ const std::shared_ptr<crow::persistent_data::UserSession> performXtokenAuth(
+ const crow::Request& req) const {
+ BMCWEB_LOG_DEBUG << "[AuthMiddleware] X-Auth-Token authentication";
- boost::string_view token = req.get_header_value("X-Auth-Token");
+ boost::string_view token = req.getHeaderValue("X-Auth-Token");
if (token.empty()) {
return nullptr;
}
auto session =
- PersistentData::SessionStore::getInstance().login_session_by_token(
- token);
+ persistent_data::SessionStore::getInstance().loginSessionByToken(token);
return session;
}
- const std::shared_ptr<crow::PersistentData::UserSession> perform_cookie_auth(
- const crow::request& req) const {
- CROW_LOG_DEBUG << "[AuthMiddleware] Cookie authentication";
+ const std::shared_ptr<crow::persistent_data::UserSession> performCookieAuth(
+ const crow::Request& req) const {
+ BMCWEB_LOG_DEBUG << "[AuthMiddleware] Cookie authentication";
- boost::string_view cookie_value = req.get_header_value("Cookie");
- if (cookie_value.empty()) {
+ boost::string_view cookieValue = req.getHeaderValue("Cookie");
+ if (cookieValue.empty()) {
return nullptr;
}
- auto start_index = cookie_value.find("SESSION=");
- if (start_index == std::string::npos) {
+ auto startIndex = cookieValue.find("SESSION=");
+ if (startIndex == std::string::npos) {
return nullptr;
}
- start_index += sizeof("SESSION=") - 1;
- auto end_index = cookie_value.find(";", start_index);
- if (end_index == std::string::npos) {
- end_index = cookie_value.size();
+ startIndex += sizeof("SESSION=") - 1;
+ auto endIndex = cookieValue.find(";", startIndex);
+ if (endIndex == std::string::npos) {
+ endIndex = cookieValue.size();
}
- boost::string_view auth_key =
- cookie_value.substr(start_index, end_index - start_index);
+ boost::string_view authKey =
+ cookieValue.substr(startIndex, endIndex - startIndex);
- const std::shared_ptr<crow::PersistentData::UserSession> session =
- PersistentData::SessionStore::getInstance().login_session_by_token(
- auth_key);
+ const std::shared_ptr<crow::persistent_data::UserSession> session =
+ persistent_data::SessionStore::getInstance().loginSessionByToken(
+ authKey);
if (session == nullptr) {
return nullptr;
}
#ifndef BMCWEB_INSECURE_DISABLE_CSRF_PREVENTION
// RFC7231 defines methods that need csrf protection
if (req.method() != "GET"_method) {
- boost::string_view csrf = req.get_header_value("X-XSRF-TOKEN");
+ boost::string_view csrf = req.getHeaderValue("X-XSRF-TOKEN");
// Make sure both tokens are filled
- if (csrf.empty() || session->csrf_token.empty()) {
+ if (csrf.empty() || session->csrfToken.empty()) {
return nullptr;
}
// Reject if csrf token not available
- if (csrf != session->csrf_token) {
+ if (csrf != session->csrfToken) {
return nullptr;
}
}
@@ -188,7 +186,7 @@ class Middleware {
}
// checks if request can be forwarded without authentication
- bool is_on_whitelist(const crow::request& req) const {
+ bool isOnWhitelist(const crow::Request& req) const {
// it's allowed to GET root node without authentica tion
if ("GET"_method == req.method()) {
if (req.url == "/redfish/v1" || req.url == "/redfish/v1/") {
@@ -217,27 +215,27 @@ class Middleware {
// routes.
// Possibly an init function on first construction?
template <typename... Middlewares>
-void request_routes(Crow<Middlewares...>& app) {
+void requestRoutes(Crow<Middlewares...>& app) {
static_assert(
- black_magic::contains<PersistentData::Middleware, Middlewares...>::value,
- "TokenAuthorization middleware must be enabled in app to use "
+ black_magic::Contains<persistent_data::Middleware, Middlewares...>::value,
+ "token_authorization middleware must be enabled in app to use "
"auth routes");
- CROW_ROUTE(app, "/login")
+ BMCWEB_ROUTE(app, "/login")
.methods(
- "POST"_method)([&](const crow::request& req, crow::response& res) {
- boost::string_view content_type = req.get_header_value("content-type");
+ "POST"_method)([&](const crow::Request& req, crow::Response& res) {
+ boost::string_view contentType = req.getHeaderValue("content-type");
boost::string_view username;
boost::string_view password;
- bool looks_like_ibm = false;
+ bool looksLikeIbm = false;
// This object needs to be declared at this scope so the strings
// within it are not destroyed before we can use them
- nlohmann::json login_credentials;
+ nlohmann::json loginCredentials;
// Check if auth was provided by a payload
- if (content_type == "application/json") {
- login_credentials = nlohmann::json::parse(req.body, nullptr, false);
- if (login_credentials.is_discarded()) {
+ if (contentType == "application/json") {
+ loginCredentials = nlohmann::json::parse(req.body, nullptr, false);
+ if (loginCredentials.is_discarded()) {
res.result(boost::beast::http::status::bad_request);
res.end();
return;
@@ -245,54 +243,51 @@ void request_routes(Crow<Middlewares...>& app) {
// check for username/password in the root object
// THis method is how intel APIs authenticate
- nlohmann::json::iterator user_it = login_credentials.find("username");
- nlohmann::json::iterator pass_it = login_credentials.find("password");
- if (user_it != login_credentials.end() &&
- pass_it != login_credentials.end()) {
- const std::string* user_str =
- user_it->get_ptr<const std::string*>();
- const std::string* pass_str =
- pass_it->get_ptr<const std::string*>();
- if (user_str != nullptr && pass_str != nullptr) {
- username = *user_str;
- password = *pass_str;
+ nlohmann::json::iterator userIt = loginCredentials.find("username");
+ nlohmann::json::iterator passIt = loginCredentials.find("password");
+ if (userIt != loginCredentials.end() &&
+ passIt != loginCredentials.end()) {
+ const std::string* userStr = userIt->get_ptr<const std::string*>();
+ const std::string* passStr = passIt->get_ptr<const std::string*>();
+ if (userStr != nullptr && passStr != nullptr) {
+ username = *userStr;
+ password = *passStr;
}
} else {
// Openbmc appears to push a data object that contains the same
// keys (username and password), attempt to use that
- auto data_it = login_credentials.find("data");
- if (data_it != login_credentials.end()) {
+ auto dataIt = loginCredentials.find("data");
+ if (dataIt != loginCredentials.end()) {
// Some apis produce an array of value ["username",
// "password"]
- if (data_it->is_array()) {
- if (data_it->size() == 2) {
- nlohmann::json::iterator user_it2 = data_it->begin();
- nlohmann::json::iterator pass_it2 = data_it->begin() + 1;
- looks_like_ibm = true;
- if (user_it2 != data_it->end() &&
- pass_it2 != data_it->end()) {
- const std::string* user_str =
- user_it2->get_ptr<const std::string*>();
- const std::string* pass_str =
- pass_it2->get_ptr<const std::string*>();
- if (user_str != nullptr && pass_str != nullptr) {
- username = *user_str;
- password = *pass_str;
+ if (dataIt->is_array()) {
+ if (dataIt->size() == 2) {
+ nlohmann::json::iterator userIt2 = dataIt->begin();
+ nlohmann::json::iterator passIt2 = dataIt->begin() + 1;
+ looksLikeIbm = true;
+ if (userIt2 != dataIt->end() && passIt2 != dataIt->end()) {
+ const std::string* userStr =
+ userIt2->get_ptr<const std::string*>();
+ const std::string* passStr =
+ passIt2->get_ptr<const std::string*>();
+ if (userStr != nullptr && passStr != nullptr) {
+ username = *userStr;
+ password = *passStr;
}
}
}
- } else if (data_it->is_object()) {
- nlohmann::json::iterator user_it2 = data_it->find("username");
- nlohmann::json::iterator pass_it2 = data_it->find("password");
- if (user_it2 != data_it->end() && pass_it2 != data_it->end()) {
- const std::string* user_str =
- user_it2->get_ptr<const std::string*>();
- const std::string* pass_str =
- pass_it2->get_ptr<const std::string*>();
- if (user_str != nullptr && pass_str != nullptr) {
- username = *user_str;
- password = *pass_str;
+ } else if (dataIt->is_object()) {
+ nlohmann::json::iterator userIt2 = dataIt->find("username");
+ nlohmann::json::iterator passIt2 = dataIt->find("password");
+ if (userIt2 != dataIt->end() && passIt2 != dataIt->end()) {
+ const std::string* userStr =
+ userIt2->get_ptr<const std::string*>();
+ const std::string* passStr =
+ passIt2->get_ptr<const std::string*>();
+ if (userStr != nullptr && passStr != nullptr) {
+ username = *userStr;
+ password = *passStr;
}
}
}
@@ -300,22 +295,22 @@ void request_routes(Crow<Middlewares...>& app) {
}
} else {
// check if auth was provided as a headers
- username = req.get_header_value("username");
- password = req.get_header_value("password");
+ username = req.getHeaderValue("username");
+ password = req.getHeaderValue("password");
}
if (!username.empty() && !password.empty()) {
- if (!pam_authenticate_user(username, password)) {
+ if (!pamAuthenticateUser(username, password)) {
res.result(boost::beast::http::status::unauthorized);
} else {
- auto session = PersistentData::SessionStore::getInstance()
- .generate_user_session(username);
+ auto session = persistent_data::SessionStore::getInstance()
+ .generateUserSession(username);
- if (looks_like_ibm) {
+ if (looksLikeIbm) {
// IBM requires a very specific login structure, and doesn't
// actually look at the status code. TODO(ed).... Fix that
// upstream
- res.json_value = {
+ res.jsonValue = {
{"data", "User '" + std::string(username) + "' logged in"},
{"message", "200 OK"},
{"status", "ok"}};
@@ -329,13 +324,13 @@ void request_routes(Crow<Middlewares...>& app) {
// "set-cookie" string into the value header, and get the result
// we want, even though we are technicaly declaring two headers
// here.
- res.add_header("Set-Cookie",
- "XSRF-TOKEN=" + session->csrf_token +
- "; Secure\r\nSet-Cookie: SESSION=" +
- session->session_token + "; Secure; HttpOnly");
+ res.addHeader("Set-Cookie",
+ "XSRF-TOKEN=" + session->csrfToken +
+ "; Secure\r\nSet-Cookie: SESSION=" +
+ session->sessionToken + "; Secure; HttpOnly");
} else {
// if content type is json, assume json token
- res.json_value = {{"token", session->session_token}};
+ res.jsonValue = {{"token", session->sessionToken}};
}
}
@@ -345,18 +340,18 @@ void request_routes(Crow<Middlewares...>& app) {
res.end();
});
- CROW_ROUTE(app, "/logout")
+ BMCWEB_ROUTE(app, "/logout")
.methods(
- "POST"_method)([&](const crow::request& req, crow::response& res) {
+ "POST"_method)([&](const crow::Request& req, crow::Response& res) {
auto& session =
- app.template get_context<TokenAuthorization::Middleware>(req)
+ app.template getContext<token_authorization::Middleware>(req)
.session;
if (session != nullptr) {
- PersistentData::SessionStore::getInstance().remove_session(session);
+ persistent_data::SessionStore::getInstance().removeSession(session);
}
res.end();
return;
});
}
-} // namespace TokenAuthorization
+} // namespace token_authorization
} // namespace crow