diff --git a/README.md b/README.md
index ccd4e759..b7bcb5cc 100644
--- a/README.md
+++ b/README.md
@@ -160,6 +160,8 @@ This library automatically validates the `exp` claim, and `nbf` is validated if
 those require setting the expected values in the `Validation` struct. In the case of `aud`, if there is a value set in the token but
 not in the `Validation`, the token will be rejected.
 
+Validation is only made on present fields in the claims. It is possible to define the required claims, hence verifying that a JWT has a value for each of these claims before it is considered for validation. The required claims can be set in the `Validation` struct. The default option requires the `exp` claim to be present.
+
 Since validating time fields is always a bit tricky due to clock skew,
 you can add some leeway to the `iat`, `exp`, and `nbf` validation by setting the `leeway` field.
 
diff --git a/examples/validation.rs b/examples/validation.rs
index 392b6b83..ffabc6f1 100644
--- a/examples/validation.rs
+++ b/examples/validation.rs
@@ -26,6 +26,7 @@ fn main() {
     let mut validation = Validation::new(Algorithm::HS256);
     validation.sub = Some("b@b.com".to_string());
     validation.set_audience(&["me"]);
+    validation.set_required_spec_claims(&["exp", "sub", "aud"]);
     let token_data = match decode::<Claims>(&token, &DecodingKey::from_secret(key), &validation) {
         Ok(c) => c,
         Err(err) => match *err.kind() {
diff --git a/src/validation.rs b/src/validation.rs
index e0d64a7c..2a8b3c94 100644
--- a/src/validation.rs
+++ b/src/validation.rs
@@ -24,6 +24,8 @@ use crate::errors::{new_error, ErrorKind, Result};
 /// // or issuer
 /// validation.set_issuer(&["Me"]); // a single string
 /// validation.set_issuer(&["Me", "You"]); // array of strings
+/// // Setting required claims
+/// validation.set_required_spec_claims(&["exp", "iss", "aud"]);
 /// ```
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct Validation {
@@ -49,29 +51,44 @@ pub struct Validation {
     ///
     /// It will return an error if the current timestamp is before the time in the `nbf` field.
     ///
+    /// Validation only happens if `nbf` claim is present in the token.
+    /// Adding `nbf` to `required_spec_claims` will make it required.
+    ///
     /// Defaults to `false`.
     pub validate_nbf: bool,
     /// Whether to validate the `aud` field.
     ///
     /// It will return an error if the `aud` field is not a member of the audience provided.
     ///
+    /// Validation only happens if `aud` claim is present in the token.
+    /// Adding `aud` to `required_spec_claims` will make it required.
+    ///
     /// Defaults to `true`. Very insecure to turn this off. Only do this if you know what you are doing.
     pub validate_aud: bool,
     /// Validation will check that the `aud` field is a member of the
     /// audience provided and will error otherwise.
     /// Use `set_audience` to set it
     ///
+    /// Validation only happens if `aud` claim is present in the token.
+    /// Adding `aud` to `required_spec_claims` will make it required.
+    ///
     /// Defaults to `None`.
     pub aud: Option<HashSet<String>>,
     /// If it contains a value, the validation will check that the `iss` field is a member of the
     /// iss provided and will error otherwise.
     /// Use `set_issuer` to set it
     ///
+    /// Validation only happens if `iss` claim is present in the token.
+    /// Adding `iss` to `required_spec_claims` will make it required.
+    ///
     /// Defaults to `None`.
     pub iss: Option<HashSet<String>>,
     /// If it contains a value, the validation will check that the `sub` field is the same as the
     /// one provided and will error otherwise.
     ///
+    /// Validation only happens if `sub` claim is present in the token.
+    /// Adding `sub` to `required_spec_claims` will make it required.
+    ///
     /// Defaults to `None`.
     pub sub: Option<String>,
     /// The validation will check that the `alg` of the header is contained