Skip to content

Commit

Permalink
fix: durations
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomsons committed Aug 17, 2023
1 parent 823a5dd commit 32c012b
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 28 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ reqwest = { version = "0.11.4", features = ["json"], optional = true }
tokio = { version = "1.9.0", features = ["sync"], optional = true }
openssl-sys = "0.9.65"
foreign-types = "0.3.2"
serde_with = "3.1.0"

[dev-dependencies]
axum = "0.1.3"
Expand Down
70 changes: 42 additions & 28 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@
#![doc = include_str!("../README.md")]
mod some;

pub mod hmac;

pub mod eddsa;

pub mod ecdsa;

pub mod rsa;

pub mod jwk;

use std::{
borrow::Cow,
Expand All @@ -18,13 +7,27 @@ use std::{
string::FromUtf8Error,
time::{Duration, SystemTime, UNIX_EPOCH},
};

use jwk::Jwk;
use openssl::error::ErrorStack;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::{Map, Value};
use serde_with::serde_as;
use smallvec::SmallVec;

use jwk::Jwk;
pub use some::*;

mod some;

pub mod hmac;

pub mod eddsa;

pub mod ecdsa;

pub mod rsa;

pub mod jwk;

/// JWT header.
#[non_exhaustive]
#[derive(Debug, Serialize, Deserialize, Default)]
Expand Down Expand Up @@ -65,15 +68,16 @@ impl<T> Default for OneOrMany<T> {
}

/// JWT Claims.
#[serde_as]
#[non_exhaustive]
#[derive(Debug, Serialize, Default, Deserialize)]
pub struct Claims<ExtraClaims> {
#[serde(skip_serializing_if = "Option::is_none")]
pub exp: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub nbf: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub iat: Option<u64>,
#[serde_as(as = "Option<serde_with::DurationSeconds<f64>>")]
pub exp: Option<Duration>,
#[serde_as(as = "Option<serde_with::DurationSeconds<f64>>")]
pub nbf: Option<Duration>,
#[serde_as(as = "Option<serde_with::DurationSeconds<f64>>")]
pub iat: Option<Duration>,

#[serde(skip_serializing_if = "Option::is_none")]
pub iss: Option<String>,
Expand Down Expand Up @@ -189,16 +193,15 @@ impl<ExtraClaims> HeaderAndClaims<ExtraClaims> {
self.claims.iat = Some(
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs(),
.unwrap(),
);
self
}

/// Check that `iat` is present and is later than `t`.
pub fn iat_is_later_than(&self, t: SystemTime) -> bool {
self.claims.iat.map_or(false, |iat| {
iat > t.duration_since(UNIX_EPOCH).unwrap().as_secs()
iat > t.duration_since(UNIX_EPOCH).unwrap()
})
}

Expand All @@ -209,7 +212,7 @@ impl<ExtraClaims> HeaderAndClaims<ExtraClaims> {
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs();
self.claims.exp = Some(t);
self.claims.exp = Some(Duration::from_secs(t));
self
}

Expand All @@ -220,7 +223,7 @@ impl<ExtraClaims> HeaderAndClaims<ExtraClaims> {
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs();
self.claims.nbf = Some(t);
self.claims.nbf = Some(Duration::from_secs(t));
self
}
}
Expand All @@ -238,8 +241,6 @@ fn url_safe_trailing_bits() -> base64::Config {
base64::URL_SAFE_NO_PAD.decode_allow_trailing_bits(true)
}

pub use some::*;

/// Encode and sign this header and claims with the signing key.
///
/// The `alg` field in header is automatically set. The `kid` claim is
Expand Down Expand Up @@ -286,13 +287,13 @@ pub fn verify<ExtraClaims: DeserializeOwned>(
// Check exp and nbf.
let now = SystemTime::now();
if let Some(exp) = claims.claims.exp {
let exp = SystemTime::UNIX_EPOCH + Duration::from_secs(exp);
let exp = SystemTime::UNIX_EPOCH + exp;
if now > exp {
return Err(Error::Expired);
}
}
if let Some(nbf) = claims.claims.nbf {
let nbf = SystemTime::UNIX_EPOCH + Duration::from_secs(nbf);
let nbf = SystemTime::UNIX_EPOCH + nbf;
if now < nbf {
return Err(Error::Before);
}
Expand Down Expand Up @@ -496,6 +497,8 @@ pub type Result<T> = std::result::Result<T, Error>;

#[cfg(test)]
mod tests {
use base64::{CharacterSet, Config};

use crate::ecdsa::{EcdsaAlgorithm, EcdsaPrivateKey};

use super::*;
Expand Down Expand Up @@ -532,4 +535,15 @@ mod tests {

Ok(())
}

#[test]
fn claim_deserialization() {
let mut json = r#"eyJpYXQiOjEuNjkyMTkwMTI1RTksImV4cCI6MS42OTIxOTM3MjVFOSwiYW50aUNzcmZUb2tlbiI6bnVsbCwic3ViIjoiYTM5ZmZjNWUtNjc5ZC00YjAzLWI5YmYtYTliZjEzNDk4NGYzIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDozOTk5L2F1dGgiLCJzZXNzaW9uSGFuZGxlIjoiNTAyMWQ2MTQtYzFmNi00ZTZkLWI1NjktZGQxN2Q0N2EyOWI0IiwicGFyZW50UmVmcmVzaFRva2VuSGFzaDEiOm51bGwsInJlZnJlc2hUb2tlbkhhc2gxIjoiNTZiMjcxZDcxNGRlMzg3M2UwMmIyZjAyYTJiZDcyYWJjZDIyZDM0NGZlZjE2YTJkMWJjYmM1NGU2YWUxN2M3OCJ9"#.as_bytes();

let r = base64::read::DecoderReader::new(&mut json, Config::new(CharacterSet::ImapMutf7, true));

let claims: Claims<Value> = serde_json::from_reader(r).unwrap();
assert_eq!(claims.iat, Some(Duration::from_secs(1692190125)));
assert_eq!(claims.exp, Some(Duration::from_secs(1692193725)));
}
}

0 comments on commit 32c012b

Please sign in to comment.