Skip to content

Commit a1ac7a0

Browse files
Add set_expires_in and set_issued_now methods (Thalhammer#322)
* Add set_expires_in and set_issued_now methods * Add a Clock type parameter for builder * set_expires_in method sets exp from the current moment * Update default traits with the new builder interface * Add VerifyTokenExpirationInValid for all traits * Use the new methods in examples * Add create method to specify the clock type * Use JWT_CLAIM_EXPLICIT for explicit constructors * Fix builder factory method in mustache file * fixup whitespace * default template was missing a few args * fix whitespace * linter --------- Co-authored-by: Chris Mc <[email protected]>
1 parent 953aab6 commit a1ac7a0

File tree

17 files changed

+143
-28
lines changed

17 files changed

+143
-28
lines changed

docs/faqs.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ Here is a simple example of creating a token that will expire in one hour:
3838

3939
```cpp
4040
auto token = jwt::create()
41-
.set_issued_at(std::chrono::system_clock::now())
42-
.set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{3600})
43-
.sign(jwt::algorithm::hs256{"secret"});
41+
.set_issued_now()
42+
.set_expires_in(std::chrono::seconds{3600})
43+
.sign(jwt::algorithm::hs256{"secret"});
4444
```
4545
4646
### Can you add claims to a signed token?

docs/signing.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ Then everything else is the same, just pass in your implementation such as:
2727
```cpp
2828
auto token = jwt::create()
2929
.set_id("custom-algo-example")
30-
.set_issued_at(std::chrono::system_clock::now())
31-
.set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{36000})
30+
.set_issued_now()
31+
.set_expires_in(std::chrono::seconds{36000})
3232
.set_payload_claim("sample", jwt::claim(std::string{"test"}))
3333
.sign(your_algorithm{/* what ever you want */});
3434
```

example/es256k.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ K9EDZi0mZ7VUeeNKq476CU5X940yusahgneePQrDMF2nWFEtBCOiXQ==
1818
.set_issuer("auth0")
1919
.set_type("JWT")
2020
.set_id("es256k-create-example")
21-
.set_issued_at(std::chrono::system_clock::now())
22-
.set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{36000})
21+
.set_issued_now()
22+
.set_expires_in(std::chrono::seconds{36000})
2323
.set_payload_claim("sample", jwt::claim(std::string{"test"}))
2424
.sign(jwt::algorithm::es256k(es256k_pub_key, es256k_priv_key, "", ""));
2525

example/partial-claim-verifier.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ rK0/Ikt5ybqUzKCMJZg2VKGTxg==
3838
.set_issuer("auth0")
3939
.set_type("JWT")
4040
.set_id("rsa-create-example")
41-
.set_issued_at(std::chrono::system_clock::now())
42-
.set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{36000})
41+
.set_issued_now()
42+
.set_expires_in(std::chrono::seconds{36000})
4343
.set_payload_claim("resource-access", role_claim)
4444
.sign(jwt::algorithm::rs256("", rsa_priv_key, "", ""));
4545

example/rsa-create.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ rK0/Ikt5ybqUzKCMJZg2VKGTxg==
3535
.set_issuer("auth0")
3636
.set_type("JWT")
3737
.set_id("rsa-create-example")
38-
.set_issued_at(std::chrono::system_clock::now())
39-
.set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{36000})
38+
.set_issued_now()
39+
.set_expires_in(std::chrono::seconds{36000})
4040
.set_payload_claim("sample", jwt::claim(std::string{"test"}))
4141
.sign(jwt::algorithm::rs256("", rsa_priv_key, "", ""));
4242

include/jwt-cpp/jwt.h

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2819,13 +2819,20 @@ namespace jwt {
28192819
* Builder class to build and sign a new token
28202820
* Use jwt::create() to get an instance of this class.
28212821
*/
2822-
template<typename json_traits>
2822+
template<typename Clock, typename json_traits>
28232823
class builder {
28242824
typename json_traits::object_type header_claims;
28252825
typename json_traits::object_type payload_claims;
28262826

2827+
/// Instance of clock type
2828+
Clock clock;
2829+
28272830
public:
2828-
builder() = default;
2831+
/**
2832+
* Constructor for building a new builder instance
2833+
* \param c Clock instance
2834+
*/
2835+
JWT_CLAIM_EXPLICIT builder(Clock c) : clock(c) {}
28292836
/**
28302837
* Set a header claim.
28312838
* \param id Name of the claim
@@ -2940,6 +2947,15 @@ namespace jwt {
29402947
* \return *this to allow for method chaining
29412948
*/
29422949
builder& set_expires_at(const date& d) { return set_payload_claim("exp", basic_claim<json_traits>(d)); }
2950+
/**
2951+
* Set expires at claim to @p d from the current moment
2952+
* \param d token expiration timeout
2953+
* \return *this to allow for method chaining
2954+
*/
2955+
template<class Rep>
2956+
builder& set_expires_in(const std::chrono::duration<Rep>& d) {
2957+
return set_payload_claim("exp", basic_claim<json_traits>(clock.now() + d));
2958+
}
29432959
/**
29442960
* Set not before claim
29452961
* \param d First valid time
@@ -2952,6 +2968,11 @@ namespace jwt {
29522968
* \return *this to allow for method chaining
29532969
*/
29542970
builder& set_issued_at(const date& d) { return set_payload_claim("iat", basic_claim<json_traits>(d)); }
2971+
/**
2972+
* Set issued at claim to the current moment
2973+
* \return *this to allow for method chaining
2974+
*/
2975+
builder& set_issued_now() { return set_issued_at(clock.now()); }
29552976
/**
29562977
* Set id claim
29572978
* \param str ID to set
@@ -3766,6 +3787,16 @@ namespace jwt {
37663787
return verifier<Clock, json_traits>(c);
37673788
}
37683789

3790+
/**
3791+
* Create a builder using the given clock
3792+
* \param c Clock instance to use
3793+
* \return builder instance
3794+
*/
3795+
template<typename Clock, typename json_traits>
3796+
builder<Clock, json_traits> create(Clock c) {
3797+
return builder<Clock, json_traits>(c);
3798+
}
3799+
37693800
/**
37703801
* Default clock class using std::chrono::system_clock as a backend.
37713802
*/
@@ -3787,8 +3818,8 @@ namespace jwt {
37873818
* Return a builder instance to create a new token
37883819
*/
37893820
template<typename json_traits>
3790-
builder<json_traits> create() {
3791-
return builder<json_traits>();
3821+
builder<default_clock, json_traits> create(default_clock c = {}) {
3822+
return builder<default_clock, json_traits>(c);
37923823
}
37933824

37943825
/**

include/jwt-cpp/traits/boost-json/defaults.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@ namespace jwt {
2525
}
2626

2727
/**
28-
* Return a builder instance to create a new token
28+
* Create a builder using the default clock
29+
* \return builder instance to create a new token
2930
*/
30-
inline builder<traits::boost_json> create() { return builder<traits::boost_json>(); }
31+
inline builder<default_clock, traits::boost_json> create() {
32+
return builder<default_clock, traits::boost_json>(default_clock{});
33+
}
3134

3235
#ifndef JWT_DISABLE_BASE64
3336
/**

include/jwt-cpp/traits/danielaparker-jsoncons/defaults.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@ namespace jwt {
2525
}
2626

2727
/**
28-
* Return a builder instance to create a new token
28+
* Create a builder using the default clock
29+
* \return builder instance to create a new token
2930
*/
30-
inline builder<traits::danielaparker_jsoncons> create() { return builder<traits::danielaparker_jsoncons>(); }
31+
inline builder<default_clock, traits::danielaparker_jsoncons> create() {
32+
return builder<default_clock, traits::danielaparker_jsoncons>(default_clock{});
33+
}
3134

3235
#ifndef JWT_DISABLE_BASE64
3336
/**

include/jwt-cpp/traits/defaults.h.mustache

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@ namespace jwt {
2727
}
2828

2929
/**
30-
* Return a builder instance to create a new token
30+
* Create a builder using the default clock
31+
* \return builder instance to create a new token
3132
*/
32-
inline builder<traits::{{traits_name}}> create() { return builder<traits::{{traits_name}}>(); }
33+
inline builder<default_clock, traits::{{traits_name}}> create() {
34+
return builder<default_clock, traits::{{traits_name}}>(default_clock{});
35+
}
3336

3437
#ifndef JWT_DISABLE_BASE64
3538
/**

include/jwt-cpp/traits/kazuho-picojson/defaults.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@ namespace jwt {
2121
}
2222

2323
/**
24-
* Return a builder instance to create a new token
24+
* Create a builder using the default clock
25+
* \return builder instance to create a new token
2526
*/
26-
inline builder<traits::kazuho_picojson> create() { return builder<traits::kazuho_picojson>(); }
27+
inline builder<default_clock, traits::kazuho_picojson> create() {
28+
return builder<default_clock, traits::kazuho_picojson>(default_clock{});
29+
}
2730

2831
#ifndef JWT_DISABLE_BASE64
2932
/**

include/jwt-cpp/traits/nlohmann-json/defaults.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@ namespace jwt {
2525
}
2626

2727
/**
28-
* Return a builder instance to create a new token
28+
* Create a builder using the default clock
29+
* \return builder instance to create a new token
2930
*/
30-
inline builder<traits::nlohmann_json> create() { return builder<traits::nlohmann_json>(); }
31+
inline builder<default_clock, traits::nlohmann_json> create() {
32+
return builder<default_clock, traits::nlohmann_json>(default_clock{});
33+
}
3134

3235
#ifndef JWT_DISABLE_BASE64
3336
/**

include/jwt-cpp/traits/open-source-parsers-jsoncpp/defaults.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ namespace jwt {
2525
}
2626

2727
/**
28-
* Return a builder instance to create a new token
28+
* Create a builder using the default clock
29+
* \return builder instance to create a new token
2930
*/
30-
inline builder<traits::open_source_parsers_jsoncpp> create() {
31-
return builder<traits::open_source_parsers_jsoncpp>();
31+
inline builder<default_clock, traits::open_source_parsers_jsoncpp> create() {
32+
return builder<default_clock, traits::open_source_parsers_jsoncpp>(default_clock{});
3233
}
3334

3435
#ifndef JWT_DISABLE_BASE64

tests/traits/BoostJsonTest.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,19 @@ TEST(BoostJsonTest, VerifyTokenExpirationValid) {
8383
verify.verify(decoded_token);
8484
}
8585

86+
TEST(BoostJsonTest, VerifyTokenExpirationInValid) {
87+
const auto token = jwt::create<jwt::traits::boost_json>()
88+
.set_issuer("auth0")
89+
.set_issued_now()
90+
.set_expires_in(std::chrono::seconds{3600})
91+
.sign(jwt::algorithm::hs256{"secret"});
92+
93+
const auto decoded_token = jwt::decode<jwt::traits::boost_json>(token);
94+
const auto verify =
95+
jwt::verify<jwt::traits::boost_json>().allow_algorithm(jwt::algorithm::hs256{"secret"}).with_issuer("auth0");
96+
verify.verify(decoded_token);
97+
}
98+
8699
TEST(BoostJsonTest, VerifyTokenExpired) {
87100
const auto token = jwt::create<jwt::traits::boost_json>()
88101
.set_issuer("auth0")

tests/traits/JsonconsTest.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,20 @@ TEST(JsonconsTest, VerifyTokenExpirationValid) {
8686
verify.verify(decoded_token);
8787
}
8888

89+
TEST(JsonconsTest, VerifyTokenExpirationInValid) {
90+
const auto token = jwt::create<jwt::traits::danielaparker_jsoncons>()
91+
.set_issuer("auth0")
92+
.set_issued_now()
93+
.set_expires_in(std::chrono::seconds{3600})
94+
.sign(jwt::algorithm::hs256{"secret"});
95+
96+
const auto decoded_token = jwt::decode<jwt::traits::danielaparker_jsoncons>(token);
97+
const auto verify = jwt::verify<jwt::traits::danielaparker_jsoncons>()
98+
.allow_algorithm(jwt::algorithm::hs256{"secret"})
99+
.with_issuer("auth0");
100+
verify.verify(decoded_token);
101+
}
102+
89103
TEST(JsonconsTest, VerifyTokenExpired) {
90104
const auto token = jwt::create<jwt::traits::danielaparker_jsoncons>()
91105
.set_issuer("auth0")

tests/traits/NlohmannTest.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,19 @@ TEST(NlohmannTest, VerifyTokenExpirationValid) {
8282
verify.verify(decoded_token);
8383
}
8484

85+
TEST(NlohmannTest, VerifyTokenExpirationInValid) {
86+
const auto token = jwt::create<jwt::traits::nlohmann_json>()
87+
.set_issuer("auth0")
88+
.set_issued_now()
89+
.set_expires_in(std::chrono::seconds{3600})
90+
.sign(jwt::algorithm::hs256{"secret"});
91+
92+
const auto decoded_token = jwt::decode<jwt::traits::nlohmann_json>(token);
93+
const auto verify =
94+
jwt::verify<jwt::traits::nlohmann_json>().allow_algorithm(jwt::algorithm::hs256{"secret"}).with_issuer("auth0");
95+
verify.verify(decoded_token);
96+
}
97+
8598
TEST(NlohmannTest, VerifyTokenExpired) {
8699
const auto token = jwt::create<jwt::traits::nlohmann_json>()
87100
.set_issuer("auth0")

tests/traits/OspJsoncppTest.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,20 @@ TEST(OspJsoncppTest, VerifyTokenExpirationValid) {
8686
verify.verify(decoded_token);
8787
}
8888

89+
TEST(OspJsoncppTest, VerifyTokenExpirationInValid) {
90+
const auto token = jwt::create<jwt::traits::open_source_parsers_jsoncpp>()
91+
.set_issuer("auth0")
92+
.set_issued_now()
93+
.set_expires_in(std::chrono::seconds{3600})
94+
.sign(jwt::algorithm::hs256{"secret"});
95+
96+
const auto decoded_token = jwt::decode<jwt::traits::open_source_parsers_jsoncpp>(token);
97+
const auto verify = jwt::verify<jwt::traits::open_source_parsers_jsoncpp>()
98+
.allow_algorithm(jwt::algorithm::hs256{"secret"})
99+
.with_issuer("auth0");
100+
verify.verify(decoded_token);
101+
}
102+
89103
TEST(OspJsoncppTest, VerifyTokenExpired) {
90104
const auto token = jwt::create<jwt::traits::open_source_parsers_jsoncpp>()
91105
.set_issuer("auth0")

tests/traits/TraitsTest.cpp.mustache

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,20 @@ TEST({{test_suite_name}}, VerifyTokenExpirationValid) {
8686
verify.verify(decoded_token);
8787
}
8888

89+
TEST({{test_suite_name}}, VerifyTokenExpirationInValid) {
90+
const auto token = jwt::create<jwt::traits::{{traits_name}}>()
91+
.set_issuer("auth0")
92+
.set_issued_now()
93+
.set_expires_in(std::chrono::seconds{3600})
94+
.sign(jwt::algorithm::hs256{"secret"});
95+
96+
const auto decoded_token = jwt::decode<jwt::traits::{{traits_name}}>(token);
97+
const auto verify = jwt::verify<jwt::traits::{{traits_name}}>()
98+
.allow_algorithm(jwt::algorithm::hs256{"secret"})
99+
.with_issuer("auth0");
100+
verify.verify(decoded_token);
101+
}
102+
89103
TEST({{test_suite_name}}, VerifyTokenExpired) {
90104
const auto token = jwt::create<jwt::traits::{{traits_name}}>()
91105
.set_issuer("auth0")

0 commit comments

Comments
 (0)