diff options
| author | Ed Tanous <ed.tanous@intel.com> | 2018-04-26 16:08:56 -0700 |
|---|---|---|
| committer | Ed Tanous <ed.tanous@intel.com> | 2018-06-29 18:18:39 +0000 |
| commit | 9bd21fc16817ab1a47e9cd4ac6baf8f5b1d4ba63 (patch) | |
| tree | 6fd10d1f64bb80abced63fe1345a87b088766d43 /include | |
| parent | e0d918bc397350aa21af3dab9faa6e21748f6373 (diff) | |
| download | bmcweb-9bd21fc16817ab1a47e9cd4ac6baf8f5b1d4ba63.tar.gz bmcweb-9bd21fc16817ab1a47e9cd4ac6baf8f5b1d4ba63.zip | |
Fix issue with basic auth and the bmcweb
This fixes a bug where the webserver requests a resource that doesn't
exist, which triggers a www-authenticate, and causes the browser to
show the wrong thing.
Change-Id: I65643a50eb269b0a7c76dcb0c65c4e7db2165c88
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
Diffstat (limited to 'include')
| -rw-r--r-- | include/http_utility.hpp | 21 | ||||
| -rw-r--r-- | include/token_authorization_middleware.hpp | 34 |
2 files changed, 49 insertions, 6 deletions
diff --git a/include/http_utility.hpp b/include/http_utility.hpp new file mode 100644 index 0000000..7b04b0f --- /dev/null +++ b/include/http_utility.hpp @@ -0,0 +1,21 @@ +#pragma once +#include <boost/algorithm/string.hpp> + +namespace http_helpers { +inline bool request_prefers_html(const crow::request& req) { + boost::string_view header = req.get_header_value("accept"); + std::vector<std::string> encodings; + // chrome currently sends 6 accepts headers, firefox sends 4. + encodings.reserve(6); + boost::split(encodings, header, boost::is_any_of(", "), + boost::token_compress_on); + for (const std::string& encoding : encodings) { + if (encoding == "text/html") { + return true; + } else if (encoding == "application/json") { + return false; + } + } + return false; +} +} // namespace http_helpers
\ No newline at end of file diff --git a/include/token_authorization_middleware.hpp b/include/token_authorization_middleware.hpp index 49649dd..0c0c474 100644 --- a/include/token_authorization_middleware.hpp +++ b/include/token_authorization_middleware.hpp @@ -44,8 +44,19 @@ class Middleware { if (ctx.session == nullptr) { CROW_LOG_WARNING << "[AuthMiddleware] authorization failed"; - res.result(boost::beast::http::status::unauthorized); - res.add_header("WWW-Authenticate", "Basic"); + // 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)) { + res.result(boost::beast::http::status::temporary_redirect); + res.add_header("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"); + } + } res.end(); return; @@ -187,7 +198,7 @@ class Middleware { if ("POST"_method == req.method()) { if ((req.url == "/redfish/v1/SessionService/Sessions") || (req.url == "/redfish/v1/SessionService/Sessions/") || - (req.url == "/login") || (req.url == "/logout")) { + (req.url == "/login")) { return true; } } @@ -302,9 +313,20 @@ void request_routes(Crow<Middlewares...>& app) { {"data", "User '" + std::string(username) + "' logged in"}, {"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"); + + // Hack alert. Boost beast by default doesn't let you declare + // multiple headers of the same name, and in most cases this is + // fine. Unfortunately here we need to set the Session cookie, + // which requires the httpOnly attribute, as well as the XSRF + // cookie, which requires it to not have an httpOnly attribute. + // To get the behavior we want, we simply inject the second + // "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"); } else { // if content type is json, assume json token res.json_value = {{"token", session->session_token}}; |

