summaryrefslogtreecommitdiff
path: root/src/mongo/crypto
diff options
context:
space:
mode:
authorSara Golemon <sara.golemon@mongodb.com>2023-01-10 14:09:01 -0600
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-01-16 00:39:01 +0000
commit0d083d50d6b988cfc18d06bed17ed58b51c9ebcc (patch)
treea9e76709e6e1a439551e793b962b6a0a63fe43ee /src/mongo/crypto
parenta2da3cb8386d5b3fb7018e870cec24122192b152 (diff)
downloadmongo-0d083d50d6b988cfc18d06bed17ed58b51c9ebcc.tar.gz
SERVER-72699 Use 'nbf' instead of 'iat' for start validity checking
Diffstat (limited to 'src/mongo/crypto')
-rw-r--r--src/mongo/crypto/jws_validated_token.cpp18
-rw-r--r--src/mongo/crypto/jwt_types.idl18
2 files changed, 21 insertions, 15 deletions
diff --git a/src/mongo/crypto/jws_validated_token.cpp b/src/mongo/crypto/jws_validated_token.cpp
index 962d9d5a9a4..6bd0713e0c6 100644
--- a/src/mongo/crypto/jws_validated_token.cpp
+++ b/src/mongo/crypto/jws_validated_token.cpp
@@ -65,15 +65,23 @@ ParsedToken parseSignedToken(StringData token) {
} // namespace
Status JWSValidatedToken::validate(const JWKManager& keyMgr) const {
- const auto nowEpoch = Date_t::now().toMillisSinceEpoch() / 1000;
- if (_body.getExpirationEpoch() < nowEpoch) {
- return Status{ErrorCodes::BadValue, "Token is expired"};
- }
+ const auto now = Date_t::now();
- if (_body.getIssuedAtEpoch() > nowEpoch) {
+ // Clock times across the network may differ and `nbf` is likely to be
+ // at or near the issue time, so provide a reasonable skew allowance.
+ constexpr Seconds kNotBeforeSkewMax{60};
+ if (_body.getNotBefore().get_value_or(Date_t::min()) > (now + kNotBeforeSkewMax)) {
return Status{ErrorCodes::BadValue, "Token not yet valid"};
}
+ // Expiration we choose not to skew, as the client can be prompted to
+ // create a new token for reauth, and indeed would since the token expiration
+ // mechanism would immediately reject this token before the command dispatch
+ // would have an opportunity to kick in.
+ if (_body.getExpiration() < now) {
+ return Status{ErrorCodes::BadValue, "Token is expired"};
+ }
+
auto tokenSplit = parseSignedToken(_originalToken);
auto signature = base64url::decode(tokenSplit.token[2]);
auto payload = tokenSplit.payload;
diff --git a/src/mongo/crypto/jwt_types.idl b/src/mongo/crypto/jwt_types.idl
index d4f5f15e418..f8cc4034e8b 100644
--- a/src/mongo/crypto/jwt_types.idl
+++ b/src/mongo/crypto/jwt_types.idl
@@ -109,15 +109,13 @@ structs:
type:
variant: [string, array<string>]
cpp_name: audience
- iat:
- description: Time at which the JWT was issued. (Unix Epoch)
- type: safeInt64
- cpp_name: issuedAtEpoch
+ nbf:
+ description: Time at which the JWT becomes valid. (Unix Epoch)
+ type: unixEpoch
+ cpp_name: notBefore
+ optional: true
exp:
description: Time at which the JWT expires. (Unix Epoch)
- type: safeInt64
- cpp_name: expirationEpoch
- auth_time:
- description: Time when the authentication occurred. (Unix Epoch)
- type: safeInt64
- optional: true
+ type: unixEpoch
+ cpp_name: expiration
+ optional: false # RFC7519 marks this optional, but we refuse to accept non-expiring tokens.