Skip to content

Commit

Permalink
add max-age, samesite options to Cookie (#1159)
Browse files Browse the repository at this point in the history
Co-authored-by: an-tao <antao2002@gmail.com>
  • Loading branch information
juanetch and an-tao committed Jan 16, 2022
1 parent bfb25a3 commit bbc3161
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 3 deletions.
57 changes: 56 additions & 1 deletion lib/inc/drogon/Cookie.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#pragma once

#include <drogon/exports.h>
#include <drogon/utils/optional.h>
#include <trantor/utils/Date.h>
#include <string>
#include <limits>
Expand All @@ -40,7 +41,13 @@ class DROGON_EXPORT Cookie
{
}
Cookie() = default;

enum class SameSite
{
kNull,
kLax,
kStrict,
kNone
};
/**
* @brief Set the Expires Date
*
Expand Down Expand Up @@ -113,6 +120,20 @@ class DROGON_EXPORT Cookie
{
value_ = std::move(value);
}
/**
* @brief Set the max-age of the cookie.
*/
void setMaxAge(int value)
{
maxAge_ = value;
}
/**
* @brief Set the same site of the cookie.
*/
void setSameSite(SameSite sameSite)
{
sameSite_ = sameSite;
}

/**
* @brief Get the string value of the cookie
Expand Down Expand Up @@ -240,6 +261,38 @@ class DROGON_EXPORT Cookie
return secure_;
}

/**
* @brief Get the max-age of the cookie
*/
optional<int> maxAge() const
{
return maxAge_;
}

/**
* @brief Get the max-age of the cookie
*/
optional<int> getMaxAge() const
{
return maxAge_;
}

/**
* @brief Get the same site of the cookie
*/
SameSite sameSite() const
{
return sameSite_;
}

/**
* @brief Get the same site of the cookie
*/
SameSite getSameSite() const
{
return sameSite_;
}

private:
trantor::Date expiresDate_{(std::numeric_limits<int64_t>::max)()};
bool httpOnly_{true};
Expand All @@ -248,6 +301,8 @@ class DROGON_EXPORT Cookie
std::string path_;
std::string key_;
std::string value_;
optional<int> maxAge_;
SameSite sameSite_{SameSite::kNull};
};

} // namespace drogon
30 changes: 29 additions & 1 deletion lib/src/Cookie.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ std::string Cookie::cookieString() const
.append(utils::getHttpFullDate(expiresDate_))
.append("; ");
}
if (maxAge_.has_value())
{
ret.append("Max-Age=")
.append(std::to_string(maxAge_.value()))
.append("; ");
}
if (!domain_.empty())
{
ret.append("Domain=").append(domain_).append("; ");
Expand All @@ -37,7 +43,29 @@ std::string Cookie::cookieString() const
{
ret.append("Path=").append(path_).append("; ");
}
if (secure_)
if (sameSite_ != SameSite::kNull)
{
switch (sameSite_)
{
case SameSite::kLax:
ret.append("SameSite=Lax; ");
break;
case SameSite::kStrict:
ret.append("SameSite=Strict; ");
break;
case SameSite::kNone:
ret.append("SameSite=None; ");
// Cookies with SameSite=None must now also specify the Secure
// attribute (they require a secure context/HTTPS).
ret.append("Secure; ");
break;
default:
// Lax replaced None as the default value to ensure that users
// have reasonably robust defense against some CSRF attacks
ret.append("SameSite=Lax; ");
}
}
if (secure_ && sameSite_ != SameSite::kNone)
{
ret.append("Secure; ");
}
Expand Down
19 changes: 19 additions & 0 deletions lib/src/HttpResponseImpl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,25 @@ void HttpResponseImpl::addHeader(const char *start,
{
cookie.setHttpOnly(true);
}
else if (cookie_name == "samesite")
{
if (cookie_value == "Lax")
{
cookie.setSameSite(Cookie::SameSite::kLax);
}
else if (cookie_value == "Strict")
{
cookie.setSameSite(Cookie::SameSite::kStrict);
}
else if (cookie_value == "None")
{
cookie.setSameSite(Cookie::SameSite::kNone);
}
}
else if (cookie_name == "max-age")
{
cookie.setMaxAge(std::stoi(cookie_value));
}
}
}
if (!cookie.key().empty())
Expand Down
12 changes: 12 additions & 0 deletions lib/tests/unittests/CookieTest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,16 @@ DROGON_TEST(CookieTest)
CHECK(cookie3.cookieString() ==
"Set-Cookie: test=3; Expires=Fri, 21 May 2021 01:45:57 GMT; "
"Domain=drogon.org; HttpOnly\r\n");

drogon::Cookie cookie4("test", "4");
cookie4.setMaxAge(3600);
cookie4.setSameSite(drogon::Cookie::SameSite::kStrict);
CHECK(cookie4.cookieString() ==
"Set-Cookie: test=4; Max-Age=3600; "