blob: 30d12c591d62efbbe800afa9b94f9afe1db9e658 [file] [log] [blame]
Ed Tanous1ccd57c2017-03-21 13:15:58 -07001#include <random>
Ed Tanousf9273472017-02-28 16:05:13 -08002#include <unordered_map>
Ed Tanousf9273472017-02-28 16:05:13 -08003#include <boost/algorithm/string/predicate.hpp>
4
5#include <token_authorization_middleware.hpp>
Ed Tanous1ccd57c2017-03-21 13:15:58 -07006#include <crow/logging.h>
Ed Tanousc4771fb2017-03-13 13:39:49 -07007#include <base64.hpp>
Ed Tanousf9273472017-02-28 16:05:13 -08008
Ed Tanousc4771fb2017-03-13 13:39:49 -07009namespace crow {
10
11using random_bytes_engine = std::independent_bits_engine<std::default_random_engine, CHAR_BIT, unsigned char>;
12
Ed Tanousf9273472017-02-28 16:05:13 -080013
Ed Tanous99923322017-03-03 14:21:24 -080014void TokenAuthorizationMiddleware::before_handle(crow::request& req, response& res, context& ctx) {
Ed Tanous9b65f1f2017-03-07 15:17:13 -080015
Ed Tanous99923322017-03-03 14:21:24 -080016 auto return_unauthorized = [&req, &res]() {
17 res.code = 401;
18 res.end();
19 };
Ed Tanous1ccd57c2017-03-21 13:15:58 -070020
21 LOG(DEBUG) << "Got route " << req.url;
22
Ed Tanous9b65f1f2017-03-07 15:17:13 -080023 if (req.url == "/" || boost::starts_with(req.url, "/static/")){
24 //TODO this is total hackery to allow the login page to work before the user
Ed Tanousc4771fb2017-03-13 13:39:49 -070025 // is authenticated. Also, it will be quite slow for all pages instead of
26 // a one time hit for the whitelist entries.
Ed Tanous9b65f1f2017-03-07 15:17:13 -080027 // Ideally, this should be done in the url router handler, with tagged routes
28 // for the whitelist entries.
Ed Tanous1ccd57c2017-03-21 13:15:58 -070029 // Another option would be to whitelist a minimal
Ed Tanous9b65f1f2017-03-07 15:17:13 -080030 return;
31 }
32
Ed Tanous99923322017-03-03 14:21:24 -080033 if (req.url == "/login") {
Ed Tanousc4771fb2017-03-13 13:39:49 -070034 if (req.method != HTTPMethod::POST){
35 return_unauthorized();
36 return;
37 } else {
38 auto login_credentials = crow::json::load(req.body);
39 if (!login_credentials){
40 return_unauthorized();
41 return;
42 }
43 auto username = login_credentials["username"].s();
44 auto password = login_credentials["password"].s();
Ed Tanous1ccd57c2017-03-21 13:15:58 -070045
46 // TODO(ed) pull real passwords from PAM
Ed Tanousc4771fb2017-03-13 13:39:49 -070047 if (username == "dude" && password == "dude"){
Ed Tanous1ccd57c2017-03-21 13:15:58 -070048 //TODO(ed) the RNG should be initialized at start, not every time we want a token
Ed Tanousc4771fb2017-03-13 13:39:49 -070049 std::random_device rand;
50 random_bytes_engine rbe;
51 std::string token('a', 20);
52 std::generate(begin(token), end(token), std::ref(rbe));
53 std::string encoded_token;
54 base64::base64_encode(token, encoded_token);
55 ctx.auth_token = encoded_token;
56 this->auth_token2 = encoded_token;
Ed Tanousc4771fb2017-03-13 13:39:49 -070057 } else {
58 return_unauthorized();
59 return;
60 }
61 }
62
63 } else if (req.url == "/logout") {
64 this->auth_token2 = "";
65 } else { // Normal, non login, non static file request
66 // Check to make sure we're logged in
67 if (this->auth_token2.empty()){
68 return_unauthorized();
69 return;
70 }
71 // Check for an authorization header, reject if not present
72 if (req.headers.count("Authorization") != 1) {
73 return_unauthorized();
74 return;
75 }
76
77 std::string auth_header = req.get_header_value("Authorization");
78 // If the user is attempting any kind of auth other than token, reject
79 if (!boost::starts_with(auth_header, "Token ")) {
80 return_unauthorized();
81 return;
82 }
83
84 //todo, use span here instead of constructing a new string
85 if (auth_header.substr(6) != this->auth_token2){
86 return_unauthorized();
87 return;
88 }
Ed Tanous1ccd57c2017-03-21 13:15:58 -070089 // else let the request continue unharmed
Ed Tanous99923322017-03-03 14:21:24 -080090 }
91}
Ed Tanousf9273472017-02-28 16:05:13 -080092
Ed Tanous99923322017-03-03 14:21:24 -080093void TokenAuthorizationMiddleware::after_handle(request& /*req*/, response& res, context& ctx) {
Ed Tanousc4771fb2017-03-13 13:39:49 -070094
Ed Tanous99923322017-03-03 14:21:24 -080095}
Ed Tanousc4771fb2017-03-13 13:39:49 -070096}