xref: /openbmc/bmcweb/include/forward_unauthorized.hpp (revision 40e9b92ec19acffb46f83a6e55b18974da5d708e)
1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3 #pragma once
4 #include "http_request.hpp"
5 #include "http_response.hpp"
6 #include "http_utility.hpp"
7 
8 #include <boost/url/format.hpp>
9 #include <boost/url/url.hpp>
10 
11 namespace forward_unauthorized
12 {
13 
14 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
15 static bool hasWebuiRoute = false;
16 
sendUnauthorized(std::string_view url,std::string_view xRequestedWith,std::string_view accept,crow::Response & res)17 inline void sendUnauthorized(std::string_view url,
18                              std::string_view xRequestedWith,
19                              std::string_view accept, crow::Response& res)
20 {
21     // If it's a browser connecting, don't send the HTTP authenticate
22     // header, to avoid possible CSRF attacks with basic auth
23     if (http_helpers::isContentTypeAllowed(
24             accept, http_helpers::ContentType::HTML, false /*allowWildcard*/))
25     {
26         // If we have a webui installed, redirect to that login page
27         if (hasWebuiRoute)
28         {
29             boost::urls::url forward =
30                 boost::urls::format("/?next={}#/login", url);
31             res.result(boost::beast::http::status::temporary_redirect);
32             res.addHeader(boost::beast::http::field::location,
33                           forward.buffer());
34             return;
35         }
36         // If we don't have a webui installed, just return an unauthorized
37         // body
38         res.result(boost::beast::http::status::unauthorized);
39         res.write(
40             "No authentication provided, and no login UI present to forward to.");
41         return;
42     }
43 
44     res.result(boost::beast::http::status::unauthorized);
45 
46     // XHR requests from a browser will set the X-Requested-With header when
47     // doing their requests, even though they might not be requesting html.
48     if (!xRequestedWith.empty())
49     {
50         return;
51     }
52     // if basic auth is disabled, don't propose it.
53     if (!persistent_data::SessionStore::getInstance()
54              .getAuthMethodsConfig()
55              .basic)
56     {
57         return;
58     }
59     res.addHeader(boost::beast::http::field::www_authenticate, "Basic");
60 }
61 } // namespace forward_unauthorized
62