blob: 51c21986d3080b8f49220bb2d92891f9554329b5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
//! Provides [`Key`] and functions to encode & decode expiring claims.
use time::OffsetDateTime;
pub use crate::signed::Key;
/// Join a string and an expiry date together into a string.
pub fn encode_expiring_claim(claim: &str, expiry_date: OffsetDateTime) -> String {
format!("{}:{}", claim, expiry_date.unix_timestamp())
}
/// Extract the string, failing if the expiry date is in the past.
pub fn decode_expiring_claim(value: String) -> Result<String,&'static str> {
let mut parts = value.rsplitn(2, ':');
let expiry_date = parts.next().expect("first .rsplitn().next() is expected to return Some");
let claim = parts.next().ok_or("expected colon")?;
let expiry_date: i64 = expiry_date.parse().map_err(|_| "failed to parse timestamp")?;
if expiry_date > OffsetDateTime::now_utc().unix_timestamp() {
Ok(claim.to_string())
} else {
Err("token is expired")
}
}
#[cfg(test)]
mod tests {
use time::{OffsetDateTime, Duration};
#[test]
fn test_expiring_claim() {
for claim in vec!["test", "", "foo:bar"] {
let encoded_claim = super::encode_expiring_claim(claim, OffsetDateTime::now_utc() + Duration::minutes(1));
assert_eq!(super::decode_expiring_claim(encoded_claim).unwrap(), claim);
let encoded_claim = super::encode_expiring_claim(claim, OffsetDateTime::now_utc() - Duration::minutes(1));
assert!(super::decode_expiring_claim(encoded_claim).is_err());
}
assert!(super::decode_expiring_claim("test".into()).is_err());
}
}
|