Skip to content

Commit

Permalink
validate_bearer_token w/o std::regex
Browse files Browse the repository at this point in the history
  • Loading branch information
mmd-osm committed Aug 3, 2024
1 parent fcf21e7 commit 209191f
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 15 deletions.
35 changes: 22 additions & 13 deletions src/oauth2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,31 +33,40 @@ inline std::string sha256_hash(const std::string& s) {

namespace oauth2 {

static constexpr auto allowed_chars = []() {
const char ALLOWED_CHARS[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~+/="; // according to RFC 6750, section 2.1
std::array<bool, 256> arr{};
for (auto j = 0; j < sizeof(ALLOWED_CHARS); j++)
arr[ALLOWED_CHARS[j]] = true;
return arr;
}();

bool has_forbidden_char(const std::string &str) {
return std::find_if(str.begin(), str.end(), [](unsigned char ch) {
return !allowed_chars[ch];
}) != str.end();
}

[[nodiscard]] std::optional<osm_user_id_t> validate_bearer_token(const request &req, data_selection& selection, bool& allow_api_write)
{

static const std::regex r(R"(Bearer ([A-Za-z0-9~_\-\.\+\/]+=*))"); // according to RFC 6750, section 2.1

const char * auth_hdr = req.get_param ("HTTP_AUTHORIZATION");
if (auth_hdr == nullptr)
return std::nullopt;

const auto auth_header = std::string(auth_hdr);

std::smatch sm;

try {
if (!std::regex_match(auth_header, sm, r))
return std::nullopt;
// Auth header starts with Bearer?
if (auth_header.rfind("Bearer ", 0) == std::string::npos)
return std::nullopt;

if (sm.size() != 2)
return std::nullopt;
const auto bearer_token = auth_header.substr(7);

} catch (std::regex_error&) {
if (bearer_token.empty())
return std::nullopt;
}

const auto& bearer_token = sm[1];
if (has_forbidden_char(bearer_token))
return std::nullopt;

bool expired;
bool revoked;
Expand Down
27 changes: 25 additions & 2 deletions test/test_oauth2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,37 @@ TEST_CASE("test_validate_bearer_token", "[oauth2]") {
CHECK(allow_api_write);
}

SECTION("Test bearer token invalid format") {
SECTION("Test bearer token invalid format (invalid chars)") {
req.set_header("HTTP_AUTHORIZATION","Bearer 6!#c23.-;<<>>");
auto res = oauth2::validate_bearer_token(req, *sel, allow_api_write);
CHECK(res == std::optional<osm_user_id_t>{});
}

SECTION("Test invalid bearer token") {
SECTION("Test bearer token invalid format (extra space after bearer)") {
req.set_header("HTTP_AUTHORIZATION","Bearer abc");
auto res = oauth2::validate_bearer_token(req, *sel, allow_api_write);
CHECK(res == std::optional<osm_user_id_t>{});
}

SECTION("Test bearer token invalid format (lowercase Bearer)") {
req.set_header("HTTP_AUTHORIZATION","bearer abc");
auto res = oauth2::validate_bearer_token(req, *sel, allow_api_write);
CHECK(res == std::optional<osm_user_id_t>{});
}

SECTION("Test bearer token invalid format (trailing space after token)") {
req.set_header("HTTP_AUTHORIZATION","Bearer abcdefghijklm ");
auto res = oauth2::validate_bearer_token(req, *sel, allow_api_write);
CHECK(res == std::optional<osm_user_id_t>{});
}

SECTION("Test bearer token invalid format (missing tokan)") {
req.set_header("HTTP_AUTHORIZATION","Bearer ");
auto res = oauth2::validate_bearer_token(req, *sel, allow_api_write);
CHECK(res == std::optional<osm_user_id_t>{});
}

SECTION("Test invalid bearer token") {
req.set_header("HTTP_AUTHORIZATION","Bearer nFRBLFyNXPKY1fiTHAIfVsjQYkCD2KoRuH66upvueaQ");
REQUIRE_THROWS_MATCHES(static_cast<void>(oauth2::validate_bearer_token(req, *sel, allow_api_write)), http::unauthorized,
Catch::Message("invalid_token"));
Expand Down

0 comments on commit 209191f

Please sign in to comment.