Compare commits
No commits in common. "main" and "ab5710a2c7e9698726784abcdfde2fc0ec66b77f" have entirely different histories.
main
...
ab5710a2c7
4 changed files with 37 additions and 25 deletions
|
@ -2,13 +2,14 @@
|
||||||
authors = ["Thomas Gideon <cmdln@thecommandline.net>"]
|
authors = ["Thomas Gideon <cmdln@thecommandline.net>"]
|
||||||
categories = ["cryptography", "authentication", "web-programming", "data-structures"]
|
categories = ["cryptography", "authentication", "web-programming", "data-structures"]
|
||||||
description = "JWT library for rust using serde, serde_json and openssl"
|
description = "JWT library for rust using serde, serde_json and openssl"
|
||||||
homepage = "https://gitea.cmdln.net/cmdln/medallion"
|
documentation = "https://cmdln.github.io/medallion/"
|
||||||
|
homepage = "http://github.com/cmdln/medallion"
|
||||||
keywords = ["JWT", "token", "web", "JSON", "RSA"]
|
keywords = ["JWT", "token", "web", "JSON", "RSA"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "medallion"
|
name = "medallion"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
repository = "https://gitea.cmdln.net/cmdln/medallion"
|
repository = "http://github.com/cmdln/medallion"
|
||||||
version = "2.5.0"
|
version = "2.4.1"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
[badges]
|
[badges]
|
||||||
[badges.travis-ci]
|
[badges.travis-ci]
|
||||||
|
@ -21,4 +22,4 @@ openssl = "~0.10.15"
|
||||||
serde = { version = "^1.0.114", features = [ "derive" ] }
|
serde = { version = "^1.0.114", features = [ "derive" ] }
|
||||||
serde_json = "^1.0.55"
|
serde_json = "^1.0.55"
|
||||||
anyhow = "^1.0.31"
|
anyhow = "^1.0.31"
|
||||||
time = "~0.3"
|
chrono = "~0.4.11"
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
Medallion
|
Medallion
|
||||||
=========
|
=========
|
||||||
|
[![Build Status](https://travis-ci.org/cmdln/medallion.svg?branch=master)](https://travis-ci.org/cmdln/medallion)
|
||||||
|
[![Crates.io Status](http://meritbadge.herokuapp.com/medallion)](https://crates.io/crates/medallion)
|
||||||
[![Documentation](https://docs.rs/medallion/badge.svg)](https://docs.rs/medallion)
|
[![Documentation](https://docs.rs/medallion/badge.svg)](https://docs.rs/medallion)
|
||||||
[![dependency status](https://deps.rs/crate/medallion/2.5.0/status.svg)](https://deps.rs/crate/medallion/2.5.0)
|
[![dependency status](https://deps.rs/crate/medallion/2.4.0/status.svg)](https://deps.rs/crate/medallion/2.4.0)
|
||||||
|
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/cmdln/medallion/master/LICENSE)
|
||||||
|
|
||||||
A JWT library for rust using serde, serde_json and openssl.
|
A JWT library for rust using serde, serde_json and openssl.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- [Documentation](https://cmdln.github.io/medallion/)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
The library provides a `Token` type that wraps headers and claims.
|
The library provides a `Token` type that wraps headers and claims.
|
||||||
|
|
18
src/lib.rs
18
src/lib.rs
|
@ -95,8 +95,8 @@ mod tests {
|
||||||
use super::Algorithm::{HS256, RS512};
|
use super::Algorithm::{HS256, RS512};
|
||||||
use crate::{DefaultPayload, DefaultToken, Header, Payload, Token};
|
use crate::{DefaultPayload, DefaultToken, Header, Payload, Token};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use chrono::{prelude::*, Duration};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use time::{Duration, OffsetDateTime};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn raw_data() {
|
pub fn raw_data() {
|
||||||
|
@ -111,11 +111,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn roundtrip_hmac() {
|
pub fn roundtrip_hmac() {
|
||||||
let now = OffsetDateTime::now_utc();
|
let now = Utc::now();
|
||||||
let header: Header<()> = Header::default();
|
let header: Header<()> = Header::default();
|
||||||
let payload = DefaultPayload {
|
let payload = DefaultPayload {
|
||||||
nbf: Some(now.unix_timestamp().try_into().unwrap()),
|
nbf: Some(now.timestamp().try_into().unwrap()),
|
||||||
exp: Some((now + Duration::minutes(5)).unix_timestamp().try_into().unwrap()),
|
exp: Some((now + Duration::minutes(5)).timestamp().try_into().unwrap()),
|
||||||
..DefaultPayload::default()
|
..DefaultPayload::default()
|
||||||
};
|
};
|
||||||
let token = Token::new(header, payload);
|
let token = Token::new(header, payload);
|
||||||
|
@ -129,7 +129,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn roundtrip_expired() -> Result<()> {
|
pub fn roundtrip_expired() -> Result<()> {
|
||||||
let now = OffsetDateTime::now_utc();
|
let now = Utc::now();
|
||||||
let token = create_for_range(now, now + Duration::minutes(-5))?;
|
let token = create_for_range(now, now + Duration::minutes(-5))?;
|
||||||
let key = b"secret";
|
let key = b"secret";
|
||||||
let raw = token.sign(key)?;
|
let raw = token.sign(key)?;
|
||||||
|
@ -142,7 +142,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn roundtrip_not_yet_valid() -> Result<()> {
|
pub fn roundtrip_not_yet_valid() -> Result<()> {
|
||||||
let now = OffsetDateTime::now_utc();
|
let now = Utc::now();
|
||||||
let token = create_for_range(now + Duration::minutes(5), now + Duration::minutes(10))?;
|
let token = create_for_range(now + Duration::minutes(5), now + Duration::minutes(10))?;
|
||||||
let key = b"secret";
|
let key = b"secret";
|
||||||
let raw = token.sign(key)?;
|
let raw = token.sign(key)?;
|
||||||
|
@ -175,11 +175,11 @@ mod tests {
|
||||||
.unwrap());
|
.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_for_range(nbf: OffsetDateTime, exp: OffsetDateTime) -> Result<Token> {
|
fn create_for_range(nbf: DateTime<Utc>, exp: DateTime<Utc>) -> Result<Token> {
|
||||||
let header: Header = Header::default();
|
let header: Header = Header::default();
|
||||||
let payload = Payload {
|
let payload = Payload {
|
||||||
nbf: Some(nbf.unix_timestamp().try_into()?),
|
nbf: Some(nbf.timestamp().try_into()?),
|
||||||
exp: Some(exp.unix_timestamp().try_into()?),
|
exp: Some(exp.timestamp().try_into()?),
|
||||||
..Payload::default()
|
..Payload::default()
|
||||||
};
|
};
|
||||||
Ok(Token::new(header, payload))
|
Ok(Token::new(header, payload))
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use super::Result;
|
use super::Result;
|
||||||
use anyhow::format_err;
|
use anyhow::format_err;
|
||||||
use base64::{decode_config, encode_config, URL_SAFE_NO_PAD};
|
use base64::{decode_config, encode_config, URL_SAFE_NO_PAD};
|
||||||
|
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
use serde_json::value::Value;
|
use serde_json::value::Value;
|
||||||
use time::{OffsetDateTime};
|
|
||||||
|
|
||||||
/// A default claim set, including the standard, or registered, claims and the ability to specify
|
/// A default claim set, including the standard, or registered, claims and the ability to specify
|
||||||
/// your own as custom claims.
|
/// your own as custom claims.
|
||||||
|
@ -81,19 +81,23 @@ impl<T: Serialize + DeserializeOwned> Payload<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify(&self) -> bool {
|
pub fn verify(&self) -> bool {
|
||||||
let now = OffsetDateTime::now_utc();
|
let now = Utc::now();
|
||||||
let nbf_verified = match self.nbf {
|
let nbf_verified = match self.nbf {
|
||||||
Some(nbf_sec) => {
|
Some(nbf_sec) => {
|
||||||
let nbf = OffsetDateTime::from_unix_timestamp(nbf_sec as i64)
|
let nbf = DateTime::<Utc>::from_utc(
|
||||||
.expect("nbf timestamp out of range");
|
NaiveDateTime::from_timestamp(nbf_sec as i64, 0),
|
||||||
|
Utc,
|
||||||
|
);
|
||||||
nbf < now
|
nbf < now
|
||||||
}
|
}
|
||||||
None => true,
|
None => true,
|
||||||
};
|
};
|
||||||
let exp_verified = match self.exp {
|
let exp_verified = match self.exp {
|
||||||
Some(exp_sec) => {
|
Some(exp_sec) => {
|
||||||
let exp = OffsetDateTime::from_unix_timestamp(exp_sec as i64)
|
let exp = DateTime::<Utc>::from_utc(
|
||||||
.expect("exp timestamp out of range");
|
NaiveDateTime::from_timestamp(exp_sec as i64, 0),
|
||||||
|
Utc,
|
||||||
|
);
|
||||||
now < exp
|
now < exp
|
||||||
}
|
}
|
||||||
None => true,
|
None => true,
|
||||||
|
@ -105,9 +109,9 @@ impl<T: Serialize + DeserializeOwned> Payload<T> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{DefaultPayload, Payload};
|
use super::{DefaultPayload, Payload};
|
||||||
|
use chrono::{prelude::*, Duration};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use time::{Duration, OffsetDateTime};
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
struct CustomClaims {
|
struct CustomClaims {
|
||||||
|
@ -207,7 +211,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_with_nbf(offset: i64) -> DefaultPayload {
|
fn create_with_nbf(offset: i64) -> DefaultPayload {
|
||||||
let nbf = (OffsetDateTime::now_utc() - Duration::minutes(offset)).unix_timestamp();
|
let nbf = (Utc::now() - Duration::minutes(offset)).timestamp();
|
||||||
DefaultPayload {
|
DefaultPayload {
|
||||||
nbf: Some(nbf as u64),
|
nbf: Some(nbf as u64),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -215,7 +219,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_with_exp(offset: i64) -> DefaultPayload {
|
fn create_with_exp(offset: i64) -> DefaultPayload {
|
||||||
let exp = (OffsetDateTime::now_utc() + Duration::minutes(offset)).unix_timestamp();
|
let exp = (Utc::now() + Duration::minutes(offset)).timestamp();
|
||||||
DefaultPayload {
|
DefaultPayload {
|
||||||
exp: Some(exp as u64),
|
exp: Some(exp as u64),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -223,8 +227,8 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_with_nbf_exp(nbf_offset: i64, exp_offset: i64) -> DefaultPayload {
|
fn create_with_nbf_exp(nbf_offset: i64, exp_offset: i64) -> DefaultPayload {
|
||||||
let nbf = (OffsetDateTime::now_utc() - Duration::minutes(nbf_offset)).unix_timestamp();
|
let nbf = (Utc::now() - Duration::minutes(nbf_offset)).timestamp();
|
||||||
let exp = (OffsetDateTime::now_utc() + Duration::minutes(exp_offset)).unix_timestamp();
|
let exp = (Utc::now() + Duration::minutes(exp_offset)).timestamp();
|
||||||
DefaultPayload {
|
DefaultPayload {
|
||||||
nbf: Some(nbf as u64),
|
nbf: Some(nbf as u64),
|
||||||
exp: Some(exp as u64),
|
exp: Some(exp as u64),
|
||||||
|
|
Loading…
Reference in a new issue