diff --git a/docs/faqs.md b/docs/faqs.md index b096f03c6..5b70a57b2 100644 --- a/docs/faqs.md +++ b/docs/faqs.md @@ -38,9 +38,9 @@ Here is a simple example of creating a token that will expire in one hour: ```cpp auto token = jwt::create() - .set_issued_at(std::chrono::system_clock::now()) - .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{3600}) - .sign(jwt::algorithm::hs256{"secret"}); + .set_issued_now() + .set_expires_in(std::chrono::seconds{3600}) + .sign(jwt::algorithm::hs256{"secret"}); ``` ### Can you add claims to a signed token? diff --git a/docs/signing.md b/docs/signing.md index a6ec5d2ff..419b7d2ad 100644 --- a/docs/signing.md +++ b/docs/signing.md @@ -27,8 +27,8 @@ Then everything else is the same, just pass in your implementation such as: ```cpp auto token = jwt::create() .set_id("custom-algo-example") - .set_issued_at(std::chrono::system_clock::now()) - .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{36000}) + .set_issued_now() + .set_expires_in(std::chrono::seconds{36000}) .set_payload_claim("sample", jwt::claim(std::string{"test"})) .sign(your_algorithm{/* what ever you want */}); ``` diff --git a/example/es256k.cpp b/example/es256k.cpp index d2a59745f..5c302f1b2 100644 --- a/example/es256k.cpp +++ b/example/es256k.cpp @@ -18,8 +18,8 @@ K9EDZi0mZ7VUeeNKq476CU5X940yusahgneePQrDMF2nWFEtBCOiXQ== .set_issuer("auth0") .set_type("JWT") .set_id("es256k-create-example") - .set_issued_at(std::chrono::system_clock::now()) - .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{36000}) + .set_issued_now() + .set_expires_in(std::chrono::seconds{36000}) .set_payload_claim("sample", jwt::claim(std::string{"test"})) .sign(jwt::algorithm::es256k(es256k_pub_key, es256k_priv_key, "", "")); diff --git a/example/partial-claim-verifier.cpp b/example/partial-claim-verifier.cpp index 6093d3be9..4f8b41c48 100644 --- a/example/partial-claim-verifier.cpp +++ b/example/partial-claim-verifier.cpp @@ -38,8 +38,8 @@ rK0/Ikt5ybqUzKCMJZg2VKGTxg== .set_issuer("auth0") .set_type("JWT") .set_id("rsa-create-example") - .set_issued_at(std::chrono::system_clock::now()) - .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{36000}) + .set_issued_now() + .set_expires_in(std::chrono::seconds{36000}) .set_payload_claim("resource-access", role_claim) .sign(jwt::algorithm::rs256("", rsa_priv_key, "", "")); diff --git a/example/rsa-create.cpp b/example/rsa-create.cpp index 16ab8f88b..d072b67fa 100644 --- a/example/rsa-create.cpp +++ b/example/rsa-create.cpp @@ -35,8 +35,8 @@ rK0/Ikt5ybqUzKCMJZg2VKGTxg== .set_issuer("auth0") .set_type("JWT") .set_id("rsa-create-example") - .set_issued_at(std::chrono::system_clock::now()) - .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{36000}) + .set_issued_now() + .set_expires_in(std::chrono::seconds{36000}) .set_payload_claim("sample", jwt::claim(std::string{"test"})) .sign(jwt::algorithm::rs256("", rsa_priv_key, "", "")); diff --git a/include/jwt-cpp/jwt.h b/include/jwt-cpp/jwt.h index fe3fd100a..45c61e07a 100644 --- a/include/jwt-cpp/jwt.h +++ b/include/jwt-cpp/jwt.h @@ -2819,13 +2819,20 @@ namespace jwt { * Builder class to build and sign a new token * Use jwt::create() to get an instance of this class. */ - template + template class builder { typename json_traits::object_type header_claims; typename json_traits::object_type payload_claims; + /// Instance of clock type + Clock clock; + public: - builder() = default; + /** + * Constructor for building a new builder instance + * \param c Clock instance + */ + JWT_CLAIM_EXPLICIT builder(Clock c) : clock(c) {} /** * Set a header claim. * \param id Name of the claim @@ -2940,6 +2947,15 @@ namespace jwt { * \return *this to allow for method chaining */ builder& set_expires_at(const date& d) { return set_payload_claim("exp", basic_claim(d)); } + /** + * Set expires at claim to @p d from the current moment + * \param d token expiration timeout + * \return *this to allow for method chaining + */ + template + builder& set_expires_in(const std::chrono::duration& d) { + return set_payload_claim("exp", basic_claim(clock.now() + d)); + } /** * Set not before claim * \param d First valid time @@ -2952,6 +2968,11 @@ namespace jwt { * \return *this to allow for method chaining */ builder& set_issued_at(const date& d) { return set_payload_claim("iat", basic_claim(d)); } + /** + * Set issued at claim to the current moment + * \return *this to allow for method chaining + */ + builder& set_issued_now() { return set_issued_at(clock.now()); } /** * Set id claim * \param str ID to set @@ -3766,6 +3787,16 @@ namespace jwt { return verifier(c); } + /** + * Create a builder using the given clock + * \param c Clock instance to use + * \return builder instance + */ + template + builder create(Clock c) { + return builder(c); + } + /** * Default clock class using std::chrono::system_clock as a backend. */ @@ -3787,8 +3818,8 @@ namespace jwt { * Return a builder instance to create a new token */ template - builder create() { - return builder(); + builder create(default_clock c = {}) { + return builder(c); } /** diff --git a/include/jwt-cpp/traits/boost-json/defaults.h b/include/jwt-cpp/traits/boost-json/defaults.h index affeffe84..56615e4e0 100644 --- a/include/jwt-cpp/traits/boost-json/defaults.h +++ b/include/jwt-cpp/traits/boost-json/defaults.h @@ -25,9 +25,12 @@ namespace jwt { } /** - * Return a builder instance to create a new token + * Create a builder using the default clock + * \return builder instance to create a new token */ - inline builder create() { return builder(); } + inline builder create() { + return builder(default_clock{}); + } #ifndef JWT_DISABLE_BASE64 /** diff --git a/include/jwt-cpp/traits/danielaparker-jsoncons/defaults.h b/include/jwt-cpp/traits/danielaparker-jsoncons/defaults.h index 47e12f5f0..f2642aa57 100644 --- a/include/jwt-cpp/traits/danielaparker-jsoncons/defaults.h +++ b/include/jwt-cpp/traits/danielaparker-jsoncons/defaults.h @@ -25,9 +25,12 @@ namespace jwt { } /** - * Return a builder instance to create a new token + * Create a builder using the default clock + * \return builder instance to create a new token */ - inline builder create() { return builder(); } + inline builder create() { + return builder(default_clock{}); + } #ifndef JWT_DISABLE_BASE64 /** diff --git a/include/jwt-cpp/traits/defaults.h.mustache b/include/jwt-cpp/traits/defaults.h.mustache index ab2a84721..e3c8fb88b 100644 --- a/include/jwt-cpp/traits/defaults.h.mustache +++ b/include/jwt-cpp/traits/defaults.h.mustache @@ -27,9 +27,12 @@ namespace jwt { } /** - * Return a builder instance to create a new token + * Create a builder using the default clock + * \return builder instance to create a new token */ - inline builder create() { return builder(); } + inline builder create() { + return builder(default_clock{}); + } #ifndef JWT_DISABLE_BASE64 /** diff --git a/include/jwt-cpp/traits/kazuho-picojson/defaults.h b/include/jwt-cpp/traits/kazuho-picojson/defaults.h index 0c82133a6..05589faab 100644 --- a/include/jwt-cpp/traits/kazuho-picojson/defaults.h +++ b/include/jwt-cpp/traits/kazuho-picojson/defaults.h @@ -21,9 +21,12 @@ namespace jwt { } /** - * Return a builder instance to create a new token + * Create a builder using the default clock + * \return builder instance to create a new token */ - inline builder create() { return builder(); } + inline builder create() { + return builder(default_clock{}); + } #ifndef JWT_DISABLE_BASE64 /** diff --git a/include/jwt-cpp/traits/nlohmann-json/defaults.h b/include/jwt-cpp/traits/nlohmann-json/defaults.h index c324075f8..0495dbd3f 100644 --- a/include/jwt-cpp/traits/nlohmann-json/defaults.h +++ b/include/jwt-cpp/traits/nlohmann-json/defaults.h @@ -25,9 +25,12 @@ namespace jwt { } /** - * Return a builder instance to create a new token + * Create a builder using the default clock + * \return builder instance to create a new token */ - inline builder create() { return builder(); } + inline builder create() { + return builder(default_clock{}); + } #ifndef JWT_DISABLE_BASE64 /** diff --git a/include/jwt-cpp/traits/open-source-parsers-jsoncpp/defaults.h b/include/jwt-cpp/traits/open-source-parsers-jsoncpp/defaults.h index 57dce4984..9f150c5ee 100644 --- a/include/jwt-cpp/traits/open-source-parsers-jsoncpp/defaults.h +++ b/include/jwt-cpp/traits/open-source-parsers-jsoncpp/defaults.h @@ -25,10 +25,11 @@ namespace jwt { } /** - * Return a builder instance to create a new token + * Create a builder using the default clock + * \return builder instance to create a new token */ - inline builder create() { - return builder(); + inline builder create() { + return builder(default_clock{}); } #ifndef JWT_DISABLE_BASE64 diff --git a/tests/traits/BoostJsonTest.cpp b/tests/traits/BoostJsonTest.cpp index 058ce3859..82c3810b3 100644 --- a/tests/traits/BoostJsonTest.cpp +++ b/tests/traits/BoostJsonTest.cpp @@ -83,6 +83,19 @@ TEST(BoostJsonTest, VerifyTokenExpirationValid) { verify.verify(decoded_token); } +TEST(BoostJsonTest, VerifyTokenExpirationInValid) { + const auto token = jwt::create() + .set_issuer("auth0") + .set_issued_now() + .set_expires_in(std::chrono::seconds{3600}) + .sign(jwt::algorithm::hs256{"secret"}); + + const auto decoded_token = jwt::decode(token); + const auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::hs256{"secret"}).with_issuer("auth0"); + verify.verify(decoded_token); +} + TEST(BoostJsonTest, VerifyTokenExpired) { const auto token = jwt::create() .set_issuer("auth0") diff --git a/tests/traits/JsonconsTest.cpp b/tests/traits/JsonconsTest.cpp index 685b1df9e..7d0f1ade4 100644 --- a/tests/traits/JsonconsTest.cpp +++ b/tests/traits/JsonconsTest.cpp @@ -86,6 +86,20 @@ TEST(JsonconsTest, VerifyTokenExpirationValid) { verify.verify(decoded_token); } +TEST(JsonconsTest, VerifyTokenExpirationInValid) { + const auto token = jwt::create() + .set_issuer("auth0") + .set_issued_now() + .set_expires_in(std::chrono::seconds{3600}) + .sign(jwt::algorithm::hs256{"secret"}); + + const auto decoded_token = jwt::decode(token); + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::hs256{"secret"}) + .with_issuer("auth0"); + verify.verify(decoded_token); +} + TEST(JsonconsTest, VerifyTokenExpired) { const auto token = jwt::create() .set_issuer("auth0") diff --git a/tests/traits/NlohmannTest.cpp b/tests/traits/NlohmannTest.cpp index faa303eee..616b622d7 100644 --- a/tests/traits/NlohmannTest.cpp +++ b/tests/traits/NlohmannTest.cpp @@ -82,6 +82,19 @@ TEST(NlohmannTest, VerifyTokenExpirationValid) { verify.verify(decoded_token); } +TEST(NlohmannTest, VerifyTokenExpirationInValid) { + const auto token = jwt::create() + .set_issuer("auth0") + .set_issued_now() + .set_expires_in(std::chrono::seconds{3600}) + .sign(jwt::algorithm::hs256{"secret"}); + + const auto decoded_token = jwt::decode(token); + const auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::hs256{"secret"}).with_issuer("auth0"); + verify.verify(decoded_token); +} + TEST(NlohmannTest, VerifyTokenExpired) { const auto token = jwt::create() .set_issuer("auth0") diff --git a/tests/traits/OspJsoncppTest.cpp b/tests/traits/OspJsoncppTest.cpp index f0bd3d533..39a6df2ff 100644 --- a/tests/traits/OspJsoncppTest.cpp +++ b/tests/traits/OspJsoncppTest.cpp @@ -86,6 +86,20 @@ TEST(OspJsoncppTest, VerifyTokenExpirationValid) { verify.verify(decoded_token); } +TEST(OspJsoncppTest, VerifyTokenExpirationInValid) { + const auto token = jwt::create() + .set_issuer("auth0") + .set_issued_now() + .set_expires_in(std::chrono::seconds{3600}) + .sign(jwt::algorithm::hs256{"secret"}); + + const auto decoded_token = jwt::decode(token); + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::hs256{"secret"}) + .with_issuer("auth0"); + verify.verify(decoded_token); +} + TEST(OspJsoncppTest, VerifyTokenExpired) { const auto token = jwt::create() .set_issuer("auth0") diff --git a/tests/traits/TraitsTest.cpp.mustache b/tests/traits/TraitsTest.cpp.mustache index db7d8c417..84ae8fceb 100644 --- a/tests/traits/TraitsTest.cpp.mustache +++ b/tests/traits/TraitsTest.cpp.mustache @@ -86,6 +86,20 @@ TEST({{test_suite_name}}, VerifyTokenExpirationValid) { verify.verify(decoded_token); } +TEST({{test_suite_name}}, VerifyTokenExpirationInValid) { + const auto token = jwt::create() + .set_issuer("auth0") + .set_issued_now() + .set_expires_in(std::chrono::seconds{3600}) + .sign(jwt::algorithm::hs256{"secret"}); + + const auto decoded_token = jwt::decode(token); + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::hs256{"secret"}) + .with_issuer("auth0"); + verify.verify(decoded_token); +} + TEST({{test_suite_name}}, VerifyTokenExpired) { const auto token = jwt::create() .set_issuer("auth0")