diff options
author | Sara Golemon <sara.golemon@mongodb.com> | 2023-01-10 14:09:01 -0600 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-01-16 00:39:01 +0000 |
commit | 0d083d50d6b988cfc18d06bed17ed58b51c9ebcc (patch) | |
tree | a9e76709e6e1a439551e793b962b6a0a63fe43ee /src/mongo/crypto | |
parent | a2da3cb8386d5b3fb7018e870cec24122192b152 (diff) | |
download | mongo-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.cpp | 18 | ||||
-rw-r--r-- | src/mongo/crypto/jwt_types.idl | 18 |
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. |