2015-10-31 11:37:15 -04:00
|
|
|
//! Create and parses JWT (JSON Web Tokens)
|
|
|
|
//!
|
2017-04-13 03:36:32 -04:00
|
|
|
//! Documentation: [stable](https://docs.rs/jsonwebtoken/)
|
2017-04-12 21:08:07 -04:00
|
|
|
#![deny(missing_docs)]
|
2017-02-22 02:45:28 -05:00
|
|
|
|
2019-06-16 11:51:43 -04:00
|
|
|
mod algorithms;
|
2018-10-28 14:58:35 -04:00
|
|
|
mod crypto;
|
2019-06-16 11:51:43 -04:00
|
|
|
/// All the errors
|
2015-10-31 11:37:15 -04:00
|
|
|
pub mod errors;
|
2017-01-09 00:50:51 -05:00
|
|
|
mod header;
|
2019-06-16 11:51:43 -04:00
|
|
|
mod keys;
|
2019-11-03 07:55:36 -05:00
|
|
|
mod pem_decoder;
|
2019-11-06 08:58:49 -05:00
|
|
|
mod pem_encoder;
|
2017-02-22 02:45:28 -05:00
|
|
|
mod serialization;
|
2017-04-11 01:41:44 -04:00
|
|
|
mod validation;
|
2016-04-02 06:41:35 -04:00
|
|
|
|
2019-06-16 11:51:43 -04:00
|
|
|
pub use algorithms::Algorithm;
|
|
|
|
pub use crypto::{sign, verify};
|
2017-08-25 04:48:53 -04:00
|
|
|
pub use header::Header;
|
2019-06-16 11:51:43 -04:00
|
|
|
pub use keys::Key;
|
2019-11-03 07:55:36 -05:00
|
|
|
pub use pem_decoder::PemEncodedKey;
|
2017-07-02 17:49:14 -04:00
|
|
|
pub use serialization::TokenData;
|
2018-10-28 14:58:35 -04:00
|
|
|
pub use validation::Validation;
|
2017-04-13 03:36:32 -04:00
|
|
|
|
2017-04-22 01:21:04 -04:00
|
|
|
use serde::de::DeserializeOwned;
|
2017-04-13 03:36:32 -04:00
|
|
|
use serde::ser::Serialize;
|
|
|
|
|
2019-07-06 14:36:32 -04:00
|
|
|
use crate::errors::{new_error, ErrorKind, Result};
|
2019-11-03 11:13:22 -05:00
|
|
|
use crate::serialization::{encode_part, from_jwt_part_claims};
|
2019-07-06 14:36:32 -04:00
|
|
|
use crate::validation::validate;
|
2017-04-13 03:36:32 -04:00
|
|
|
|
|
|
|
/// Encode the header and claims given and sign the payload using the algorithm from the header and the key
|
|
|
|
///
|
|
|
|
/// ```rust,ignore
|
|
|
|
/// #[macro_use]
|
|
|
|
/// extern crate serde_derive;
|
|
|
|
/// use jsonwebtoken::{encode, Algorithm, Header};
|
|
|
|
///
|
|
|
|
/// /// #[derive(Debug, Serialize, Deserialize)]
|
|
|
|
/// struct Claims {
|
|
|
|
/// sub: String,
|
|
|
|
/// company: String
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// let my_claims = Claims {
|
|
|
|
/// sub: "b@b.com".to_owned(),
|
|
|
|
/// company: "ACME".to_owned()
|
|
|
|
/// };
|
|
|
|
///
|
|
|
|
/// // my_claims is a struct that implements Serialize
|
|
|
|
/// // This will create a JWT using HS256 as algorithm
|
2019-06-16 11:51:43 -04:00
|
|
|
/// let token = encode(&Header::default(), &my_claims, Key::Hmac("secret".as_ref())).unwrap();
|
2017-04-13 03:36:32 -04:00
|
|
|
/// ```
|
2019-06-16 11:51:43 -04:00
|
|
|
pub fn encode<T: Serialize>(header: &Header, claims: &T, key: Key) -> Result<String> {
|
2019-11-03 11:13:22 -05:00
|
|
|
let encoded_header = encode_part(&header)?;
|
|
|
|
let encoded_claims = encode_part(&claims)?;
|
2017-04-13 03:36:32 -04:00
|
|
|
let signing_input = [encoded_header.as_ref(), encoded_claims.as_ref()].join(".");
|
2018-10-28 14:58:06 -04:00
|
|
|
let signature = sign(&*signing_input, key, header.alg)?;
|
2017-04-13 03:36:32 -04:00
|
|
|
|
|
|
|
Ok([signing_input, signature].join("."))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Used in decode: takes the result of a rsplit and ensure we only get 2 parts
|
|
|
|
/// Errors if we don't
|
|
|
|
macro_rules! expect_two {
|
|
|
|
($iter:expr) => {{
|
|
|
|
let mut i = $iter;
|
|
|
|
match (i.next(), i.next(), i.next()) {
|
|
|
|
(Some(first), Some(second), None) => (first, second),
|
2018-10-28 14:58:35 -04:00
|
|
|
_ => return Err(new_error(ErrorKind::InvalidToken)),
|
2017-04-13 03:36:32 -04:00
|
|
|
}
|
2018-10-28 14:58:35 -04:00
|
|
|
}};
|
2017-04-13 03:36:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Decode a token into a struct containing 2 fields: `claims` and `header`.
|
|
|
|
///
|
|
|
|
/// If the token or its signature is invalid or the claims fail validation, it will return an error.
|
|
|
|
///
|
|
|
|
/// ```rust,ignore
|
|
|
|
/// #[macro_use]
|
|
|
|
/// extern crate serde_derive;
|
2017-10-22 07:20:01 -04:00
|
|
|
/// use jsonwebtoken::{decode, Validation, Algorithm};
|
2017-04-13 03:36:32 -04:00
|
|
|
///
|
|
|
|
/// #[derive(Debug, Serialize, Deserialize)]
|
|
|
|
/// struct Claims {
|
|
|
|
/// sub: String,
|
|
|
|
/// company: String
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// let token = "a.jwt.token".to_string();
|
|
|
|
/// // Claims is a struct that implements Deserialize
|
2019-06-16 11:51:43 -04:00
|
|
|
/// let token_data = decode::<Claims>(&token, Key::Hmac("secret"), &Validation::new(Algorithm::HS256));
|
2017-04-13 03:36:32 -04:00
|
|
|
/// ```
|
2018-10-28 14:58:35 -04:00
|
|
|
pub fn decode<T: DeserializeOwned>(
|
|
|
|
token: &str,
|
2019-06-16 11:51:43 -04:00
|
|
|
key: Key,
|
2018-10-28 14:58:35 -04:00
|
|
|
validation: &Validation,
|
|
|
|
) -> Result<TokenData<T>> {
|
2017-04-13 03:36:32 -04:00
|
|
|
let (signature, signing_input) = expect_two!(token.rsplitn(2, '.'));
|
2017-04-22 02:21:16 -04:00
|
|
|
let (claims, header) = expect_two!(signing_input.rsplitn(2, '.'));
|
2019-11-03 11:13:22 -05:00
|
|
|
let header = Header::from_encoded(header)?;
|
2017-04-13 03:36:32 -04:00
|
|
|
|
2017-08-25 04:48:53 -04:00
|
|
|
if !verify(signature, signing_input, key, header.alg)? {
|
2018-07-25 08:43:58 -04:00
|
|
|
return Err(new_error(ErrorKind::InvalidSignature));
|
2017-04-13 03:36:32 -04:00
|
|
|
}
|
|
|
|
|
2017-10-22 07:20:01 -04:00
|
|
|
if !validation.algorithms.contains(&header.alg) {
|
2018-07-25 08:43:58 -04:00
|
|
|
return Err(new_error(ErrorKind::InvalidAlgorithm));
|
2017-04-13 03:36:32 -04:00
|
|
|
}
|
2017-04-22 02:21:16 -04:00
|
|
|
|
2018-10-28 14:58:35 -04:00
|
|
|
let (decoded_claims, claims_map): (T, _) = from_jwt_part_claims(claims)?;
|
2017-04-14 07:32:39 -04:00
|
|
|
validate(&claims_map, validation)?;
|
2017-04-13 03:36:32 -04:00
|
|
|
|
2018-07-25 09:42:00 -04:00
|
|
|
Ok(TokenData { header, claims: decoded_claims })
|
2017-04-13 03:36:32 -04:00
|
|
|
}
|
2017-08-25 04:48:53 -04:00
|
|
|
|
2018-03-03 12:50:03 -05:00
|
|
|
/// Decode a token without any signature validation into a struct containing 2 fields: `claims` and `header`.
|
|
|
|
///
|
|
|
|
/// NOTE: Do not use this unless you know what you are doing! If the token's signature is invalid, it will *not* return an error.
|
|
|
|
///
|
|
|
|
/// ```rust,ignore
|
|
|
|
/// #[macro_use]
|
|
|
|
/// extern crate serde_derive;
|
|
|
|
/// use jsonwebtoken::{dangerous_unsafe_decode, Validation, Algorithm};
|
|
|
|
///
|
|
|
|
/// #[derive(Debug, Serialize, Deserialize)]
|
|
|
|
/// struct Claims {
|
|
|
|
/// sub: String,
|
|
|
|
/// company: String
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// let token = "a.jwt.token".to_string();
|
|
|
|
/// // Claims is a struct that implements Deserialize
|
|
|
|
/// let token_data = dangerous_unsafe_decode::<Claims>(&token, &Validation::new(Algorithm::HS256));
|
|
|
|
/// ```
|
|
|
|
pub fn dangerous_unsafe_decode<T: DeserializeOwned>(token: &str) -> Result<TokenData<T>> {
|
|
|
|
let (_, signing_input) = expect_two!(token.rsplitn(2, '.'));
|
|
|
|
let (claims, header) = expect_two!(signing_input.rsplitn(2, '.'));
|
2019-11-03 11:13:22 -05:00
|
|
|
let header = Header::from_encoded(header)?;
|
2018-03-03 12:50:03 -05:00
|
|
|
|
2018-10-28 14:58:35 -04:00
|
|
|
let (decoded_claims, _): (T, _) = from_jwt_part_claims(claims)?;
|
2018-03-03 12:50:03 -05:00
|
|
|
|
2018-10-28 14:58:06 -04:00
|
|
|
Ok(TokenData { header, claims: decoded_claims })
|
2018-03-03 12:50:03 -05:00
|
|
|
}
|
|
|
|
|
2017-08-25 04:48:53 -04:00
|
|
|
/// Decode a token and return the Header. This is not doing any kind of validation: it is meant to be
|
2017-09-08 03:23:15 -04:00
|
|
|
/// used when you don't know which `alg` the token is using and want to find out.
|
2017-08-25 04:48:53 -04:00
|
|
|
///
|
2017-09-08 03:23:15 -04:00
|
|
|
/// If the token has an invalid format, it will return an error.
|
2017-08-25 04:48:53 -04:00
|
|
|
///
|
|
|
|
/// ```rust,ignore
|
|
|
|
/// use jsonwebtoken::decode_header;
|
|
|
|
///
|
|
|
|
/// let token = "a.jwt.token".to_string();
|
|
|
|
/// let header = decode_header(&token);
|
|
|
|
/// ```
|
|
|
|
pub fn decode_header(token: &str) -> Result<Header> {
|
|
|
|
let (_, signing_input) = expect_two!(token.rsplitn(2, '.'));
|
|
|
|
let (_, header) = expect_two!(signing_input.rsplitn(2, '.'));
|
2019-11-03 11:13:22 -05:00
|
|
|
Header::from_encoded(header)
|
2017-08-25 04:48:53 -04:00
|
|
|
}
|
2019-11-03 07:22:51 -05:00
|
|
|
|
|
|
|
/// Decode a PEM string to obtain its key
|
|
|
|
///
|
|
|
|
/// This must be a tagged PEM encoded key, tags start with `-----BEGIN ..-----`
|
|
|
|
/// and end with a `-----END ..-----`
|
2019-11-03 07:55:36 -05:00
|
|
|
///
|
2019-11-03 07:22:51 -05:00
|
|
|
/// ```rust
|
|
|
|
/// use jsonwebtoken::{decode_pem, sign, verify, Algorithm};
|
2019-11-03 07:55:36 -05:00
|
|
|
///
|
2019-11-03 07:22:51 -05:00
|
|
|
/// let pem_content = "-----BEGIN PRIVATE KEY-----
|
|
|
|
/// MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWTFfCGljY6aw3Hrt
|
|
|
|
/// kHmPRiazukxPLb6ilpRAewjW8nihRANCAATDskChT+Altkm9X7MI69T3IUmrQU0L
|
|
|
|
/// 950IxEzvw/x5BMEINRMrXLBJhqzO9Bm+d6JbqA21YQmd1Kt4RzLJR1W+
|
|
|
|
/// -----END PRIVATE KEY-----";
|
2019-11-03 07:55:36 -05:00
|
|
|
///
|
2019-11-03 07:22:51 -05:00
|
|
|
/// // First use decode_pem from jsonwebtoken
|
|
|
|
/// let privkey_pem = decode_pem(pem_content).unwrap();
|
|
|
|
/// // If it decodes Ok, then you can start using it with a given algorithm
|
|
|
|
/// let privkey = privkey_pem.as_key().unwrap();
|
2019-11-03 07:55:36 -05:00
|
|
|
///
|
2019-11-03 07:22:51 -05:00
|
|
|
/// // When using the as_key function, you do not need to wrap in Key::Der or Key::Pkcs8
|
|
|
|
/// // The same code can be used for public keys too.
|
|
|
|
/// let encrypted = sign("hello world", privkey, Algorithm::ES256).unwrap();
|
|
|
|
/// ```
|
|
|
|
pub fn decode_pem(content: &str) -> Result<PemEncodedKey> {
|
|
|
|
PemEncodedKey::read(content)
|
|
|
|
}
|
2019-11-06 08:58:49 -05:00
|
|
|
|
|
|
|
/// TODO
|
|
|
|
pub fn encode_rsa_public_pkcs1_pem(modulus: &[u8], exponent: &[u8]) -> Result<String> {
|
|
|
|
pem_encoder::encode_rsa_public_pkcs1_pem(modulus, exponent)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// TODO
|
|
|
|
pub fn encode_rsa_public_pkcs1_der(modulus: &[u8], exponent: &[u8]) -> Result<Vec<u8>> {
|
|
|
|
pem_encoder::encode_rsa_public_pkcs1_der(modulus, exponent)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// TODO
|
|
|
|
pub fn encode_rsa_public_pkcs8_pem(modulus: &[u8], exponent: &[u8]) -> Result<String> {
|
|
|
|
pem_encoder::encode_rsa_public_pkcs8_pem(modulus, exponent)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// TODO
|
|
|
|
pub fn encode_rsa_public_pkcs8_der(modulus: &[u8], exponent: &[u8]) -> Result<Vec<u8>> {
|
|
|
|
pem_encoder::encode_rsa_public_pkcs8_der(modulus, exponent)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// TODO
|
|
|
|
pub fn encode_ec_public_pem(x_coordinate: &[u8]) -> Result<String> {
|
|
|
|
pem_encoder::encode_ec_public_pem(x_coordinate)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// TODO
|
|
|
|
pub fn encode_ec_public_der(x_coordinate: &[u8]) -> Result<Vec<u8>> {
|
|
|
|
pem_encoder::encode_ec_public_der(x_coordinate)
|
2019-11-06 13:30:59 -05:00
|
|
|
}
|