Switch to failure (#6)

* Switch to failure

* Bump version
This commit is contained in:
Thomas Gideon 2018-11-16 17:28:01 -05:00 committed by GitHub
parent 1b594ff60e
commit 7fcae534f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 49 additions and 118 deletions

View file

@ -2,23 +2,24 @@
authors = ["Thomas Gideon <cmdln@thecommandline.net>"]
categories = ["cryptography", "authentication", "web-programming", "data-structures"]
description = "JWT library for rust using serde, serde_json and openssl"
documentation = "https://commandline.github.io/medallion/"
homepage = "http://github.com/commandline/medallion"
documentation = "https://cmdln.github.io/medallion/"
homepage = "http://github.com/cmdln/medallion"
keywords = ["JWT", "token", "web", "JSON", "RSA"]
license = "MIT"
name = "medallion"
readme = "README.md"
repository = "http://github.com/commandline/medallion"
version = "2.2.3"
repository = "http://github.com/cmdn/medallion"
version = "2.3.0"
[badges]
[badges.travis-ci]
branch = "master"
repository = "https://travis-ci.org/commandline/medallion"
repository = "https://travis-ci.org/cmdln/medallion"
[dependencies]
base64 = "0.9"
openssl = "0.10"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
time = "0.1"
base64 = "~0.10.0"
failure = "~0.1.3"
openssl = "~0.10.15"
serde = "^1.0.80"
serde_derive = "^1.0.80"
serde_json = "^1.0.33"
time = "~0.1.40"

View file

@ -1,10 +1,13 @@
use base64::{decode_config, encode_config, URL_SAFE_NO_PAD};
use header::Algorithm;
use openssl::hash::MessageDigest;
use openssl::memcmp;
use openssl::pkey::PKey;
use openssl::rsa::Rsa;
use openssl::sign::{Signer, Verifier};
use openssl::{
hash::MessageDigest,
memcmp,
pkey::PKey,
rsa::Rsa,
sign::{Signer, Verifier},
};
use super::Result;
pub fn sign(data: &str, key: &[u8], algorithm: &Algorithm) -> Result<String> {
@ -72,9 +75,9 @@ fn verify_rsa(signature: &str, data: &str, key: &[u8], digest: MessageDigest) ->
#[cfg(test)]
pub mod tests {
use super::{sign, verify};
use header::Algorithm;
use openssl;
use super::{sign, verify};
#[test]
pub fn sign_data_hmac() {
@ -83,7 +86,7 @@ pub mod tests {
let real_sig = "TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ";
let data = format!("{}.{}", header, claims);
let sig = sign(&*data, "secret".as_bytes(), &Algorithm::HS256);
let sig = sign(&*data, b"secret", &Algorithm::HS256);
assert_eq!(sig.unwrap(), real_sig);
}
@ -120,6 +123,6 @@ pub mod tests {
let target = "TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ";
let data = format!("{}.{}", header, claims);
assert!(verify(target, &*data, "secret".as_bytes(), &Algorithm::HS256).unwrap());
assert!(verify(target, &*data, b"secret", &Algorithm::HS256).unwrap());
}
}

View file

@ -1,67 +1,3 @@
use base64::DecodeError;
use serde_json;
use std::error;
use std::fmt;
use std::string::FromUtf8Error;
use openssl::error::ErrorStack;
use failure::Error;
#[derive(Debug)]
pub enum Error {
/// Custom, Medallion specific errors.
Custom(String),
/// String encoding errors.
Utf8(FromUtf8Error),
/// Base64 encoding or decoding errors.
Base64(DecodeError),
/// JSON parsing or stringifying errors.
JSON(serde_json::Error),
/// Errors from RSA operations.
Crypto(ErrorStack),
}
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::Custom(ref message) => message,
Error::Utf8(ref err) => err.description(),
Error::Base64(ref err) => err.description(),
Error::JSON(ref err) => err.description(),
Error::Crypto(ref err) => err.description(),
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
Error::Custom(_) => None,
Error::Utf8(ref err) => Some(err),
Error::Base64(ref err) => Some(err),
Error::JSON(ref err) => Some(err),
Error::Crypto(ref err) => Some(err),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Custom(ref message) => f.write_str(message),
Error::Utf8(ref err) => err.fmt(f),
Error::Base64(ref err) => err.fmt(f),
Error::JSON(ref err) => err.fmt(f),
Error::Crypto(ref err) => err.fmt(f),
}
}
}
macro_rules! error_wrap {
($f: ty, $e: expr) => {
impl From<$f> for Error {
fn from(f: $f) -> Error { $e(f) }
}
}
}
error_wrap!(FromUtf8Error, Error::Utf8);
error_wrap!(DecodeError, Error::Base64);
error_wrap!(serde_json::Error, Error::JSON);
error_wrap!(ErrorStack, Error::Crypto);
pub type Result<T> = std::result::Result<T, Error>;

View file

@ -1,10 +1,7 @@
use base64::{decode_config, encode_config, URL_SAFE_NO_PAD};
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde::{de::DeserializeOwned, Serialize};
use serde_json::{self, Value};
use std::default::Default;
use super::error::Error;
use super::Result;
/// An extensible Header that provides only algorithm field and allows for additional fields to be
@ -55,9 +52,7 @@ impl<T: Serialize + DeserializeOwned> Header<T> {
let enc = encode_config((&*s).as_bytes(), URL_SAFE_NO_PAD);
Ok(enc)
} else {
Err(Error::Custom(
"Could not access additional headers.".to_owned(),
))
Err(format_err!("Could not access additional headers."))
}
}
None => {
@ -67,7 +62,7 @@ impl<T: Serialize + DeserializeOwned> Header<T> {
}
}
} else {
Err(Error::Custom("Could not access default header.".to_owned()))
Err(format_err!("Could not access default header."))
}
}
}
@ -113,7 +108,7 @@ mod tests {
#[test]
fn to_base64() {
let enc = "eyJhbGciOiJIUzI1NiJ9";
let header: Header<()> = Default::default();
let header: Header<()> = Header::default();
assert_eq!(enc, header.to_base64().unwrap());
}
@ -126,7 +121,7 @@ mod tests {
kid: "1KSF3g".into(),
typ: "JWT".into(),
}),
..Default::default()
..Header::default()
};
assert_eq!(enc, header.to_base64().unwrap());
@ -134,7 +129,7 @@ mod tests {
#[test]
fn roundtrip() {
let header: Header<()> = Default::default();
let header: Header<()> = Header::default();
let enc = header.to_base64().unwrap();
assert_eq!(header, Header::from_base64(&*enc).unwrap());
}

View file

@ -7,6 +7,8 @@
///! Tries to support the standard uses for JWTs while providing reasonable ways to extend,
///! primarily by adding custom headers and claims to tokens.
extern crate base64;
#[macro_use]
extern crate failure;
extern crate openssl;
extern crate serde;
#[macro_use]
@ -14,19 +16,16 @@ extern crate serde_derive;
extern crate serde_json;
extern crate time;
pub use error::Error;
pub use header::Algorithm;
pub use header::Header;
pub use header::{Algorithm, Header};
pub use payload::{DefaultPayload, Payload};
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde::{de::DeserializeOwned, Serialize};
mod crypt;
pub mod error;
mod error;
mod header;
mod payload;
pub type Result<T> = std::result::Result<T, Error>;
pub use error::Result;
/// A convenient type that binds the same type parameter for the custom claims, an empty tuple, as
/// `DefaultPayload` so that the two aliases may be used together to reduce boilerplate when no
@ -118,7 +117,7 @@ mod tests {
let token = DefaultToken::<()>::parse(raw).unwrap();
assert_eq!(token.header.alg, HS256);
assert!(token.verify("secret".as_bytes()).unwrap());
assert!(token.verify(b"secret").unwrap());
}
#[test]
@ -131,7 +130,7 @@ mod tests {
..DefaultPayload::default()
};
let token = Token::new(header, payload);
let key = "secret".as_bytes();
let key = b"secret";
let raw = token.sign(key).unwrap();
let same = Token::parse(&*raw).unwrap();
@ -143,7 +142,7 @@ mod tests {
pub fn roundtrip_expired() {
let now = time::now();
let token = create_for_range(now, now + Duration::minutes(-5));
let key = "secret".as_bytes();
let key = b"secret";
let raw = token.sign(key).unwrap();
let same = Token::parse(&*raw).unwrap();
@ -155,7 +154,7 @@ mod tests {
pub fn roundtrip_not_yet_valid() {
let now = time::now();
let token = create_for_range(now + Duration::minutes(5), now + Duration::minutes(10));
let key = "secret".as_bytes();
let key = b"secret";
let raw = token.sign(key).unwrap();
let same = Token::parse(&*raw).unwrap();
@ -171,7 +170,7 @@ mod tests {
..Header::default()
};
let token = DefaultToken {
header: header,
header,
..Token::default()
};
let raw = token

View file

@ -1,6 +1,5 @@
use super::Result;
use base64::{decode_config, encode_config, URL_SAFE_NO_PAD};
use error::Error;
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde_json;
@ -68,7 +67,7 @@ impl<T: Serialize + DeserializeOwned> Payload<T> {
let enc = encode_config((&*s).as_bytes(), URL_SAFE_NO_PAD);
Ok(enc)
} else {
Err(Error::Custom("Could not access custom claims.".to_owned()))
Err(format_err!("Could not access custom claims."))
}
}
None => {
@ -78,9 +77,7 @@ impl<T: Serialize + DeserializeOwned> Payload<T> {
}
}
} else {
Err(Error::Custom(
"Could not access standard claims.".to_owned(),
))
Err(format_err!("Could not access standard claims.",))
}
}
@ -234,10 +231,10 @@ mod tests {
fn create_default() -> DefaultPayload {
DefaultPayload {
aud: Some("login_service".into()),
iat: Some(1302317100),
iat: Some(1_302_317_100),
iss: Some("example.com".into()),
exp: Some(1302319100),
nbf: Some(1302317100),
exp: Some(1_302_319_100),
nbf: Some(1_302_317_100),
sub: Some("Random User".into()),
..Default::default()
}
@ -246,8 +243,8 @@ mod tests {
fn create_custom() -> Payload<CustomClaims> {
Payload {
iss: Some("example.com".into()),
iat: Some(1302317100),
exp: Some(1302319100),
iat: Some(1_302_317_100),
exp: Some(1_302_319_100),
claims: Some(CustomClaims {
user_id: "123456".into(),
is_admin: false,