#![deny(missing_docs)]
#![cfg_attr(feature = "cargo-clippy", allow(unseparated_literal_suffix))]
extern crate base64;
extern crate byteorder;
extern crate chrono;
extern crate ring;
extern crate serde;
extern crate serde_json;
extern crate untrusted;
#[macro_use]
extern crate bitflags;
#[macro_use]
mod macros;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate slog;
#[macro_use]
extern crate twist;
mod client;
mod error;
mod server;
mod sign;
mod util;
pub mod encode;
pub mod decode;
pub mod verify;
use error::TwistJwt;
use std::fmt;
pub use server::Jwt as ServerJwt;
pub use client::Jwt as ClientJwt;
const RSV3: u8 = 1;
const SWE: &'static str = "Sec-WebSocket-Extensions: ";
const PMJWT: &'static str = "permessage-jwt";
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub enum Algorithm {
HS256,
HS384,
HS512,
PS256,
PS384,
PS512,
RS256,
RS384,
RS512,
}
impl Default for Algorithm {
fn default() -> Algorithm {
Algorithm::HS256
}
}
impl fmt::Display for Algorithm {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Algorithm::HS256 => write!(f, "HS256"),
Algorithm::HS384 => write!(f, "HS384"),
Algorithm::HS512 => write!(f, "HS512"),
Algorithm::PS256 => write!(f, "PS256"),
Algorithm::PS384 => write!(f, "PS384"),
Algorithm::PS512 => write!(f, "PS512"),
Algorithm::RS256 => write!(f, "RS256"),
Algorithm::RS384 => write!(f, "RS384"),
Algorithm::RS512 => write!(f, "RS512"),
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Header {
alg: Algorithm,
typ: String,
#[serde(skip_serializing_if = "Option::is_none")]
jku: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
jwk: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
kid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
x5u: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
x5c: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
x5t: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename="x5t#S256")]
x5ts256: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
cty: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
crit: Option<Vec<String>>,
}
impl Header {
pub fn alg(&self) -> Algorithm {
self.alg
}
pub fn set_alg(&mut self, alg: Algorithm) -> &mut Header {
self.alg = alg;
self
}
pub fn typ(&self) -> &str {
&self.typ
}
pub fn jku(&self) -> &str {
if let Some(ref jku) = self.jku {
jku
} else {
""
}
}
pub fn set_jku(&mut self, jku: &str) -> &mut Header {
self.jku = Some(jku.to_string());
self
}
pub fn jwk(&self) -> &str {
if let Some(ref jwk) = self.jwk {
jwk
} else {
""
}
}
pub fn set_jwk(&mut self, jwk: &str) -> &mut Header {
self.jwk = Some(jwk.to_string());
self
}
pub fn kid(&self) -> &str {
if let Some(ref kid) = self.kid {
kid
} else {
""
}
}
pub fn set_kid(&mut self, kid: &str) -> &mut Header {
self.kid = Some(kid.to_string());
self
}
pub fn x5u(&self) -> &str {
if let Some(ref x5u) = self.x5u {
x5u
} else {
""
}
}
pub fn set_x5u(&mut self, x5u: &str) -> &mut Header {
self.x5u = Some(x5u.to_string());
self
}
pub fn x5c(&self) -> &str {
if let Some(ref x5c) = self.x5c {
x5c
} else {
""
}
}
pub fn set_x5c(&mut self, x5c: &str) -> &mut Header {
self.x5c = Some(x5c.to_string());
self
}
pub fn x5t(&self) -> &str {
if let Some(ref x5t) = self.x5c {
x5t
} else {
""
}
}
pub fn set_x5t(&mut self, x5t: &str) -> &mut Header {
self.x5t = Some(x5t.to_string());
self
}
pub fn x5ts256(&self) -> &str {
if let Some(ref x5ts256) = self.x5ts256 {
x5ts256
} else {
""
}
}
pub fn set_x5ts256(&mut self, x5ts256: &str) -> &mut Header {
self.x5ts256 = Some(x5ts256.to_string());
self
}
pub fn cty(&self) -> &str {
if let Some(ref cty) = self.cty {
cty
} else {
""
}
}
pub fn set_cty(&mut self, cty: &str) -> &mut Header {
self.cty = Some(cty.to_string());
self
}
pub fn crit(&self) -> Vec<String> {
if let Some(ref crit) = self.crit {
crit.clone()
} else {
Vec::new()
}
}
pub fn set_crit(&mut self, crit: Vec<String>) -> &mut Header {
self.crit = Some(crit);
self
}
}
impl Default for Header {
fn default() -> Header {
Header {
alg: Algorithm::HS256,
typ: "JWT".to_string(),
jku: None,
jwk: None,
kid: None,
x5u: None,
x5c: None,
x5t: None,
x5ts256: None,
cty: None,
crit: None,
}
}
}
pub struct TokenData<T> {
header: Header,
claims: T,
}
impl<T> TokenData<T> {
pub fn header(&self) -> Header {
self.header.clone()
}
pub fn claims(&self) -> T
where T: Clone
{
self.claims.clone()
}
}
pub type TwistJwtResult<T> = Result<T, TwistJwt>;
#[cfg(test)]
mod test {
pub const HS256: &'static str = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\
.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9\
.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ";
pub const HS384: &'static str = "eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.\
DtVnCyiYCsCbg8gUP-579IC2GJ7P3CtFw6nfTTPw-0lZUzqgWAo9QIQElyxOpoRm";
pub const HS512: &'static str = "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.\
YI0rUGDq5XdRw8vW2sDLRNFMN8Waol03iSFH8I4iLzuYK7FKHaQYWzPt0BJFGrAmKJ6SjY0mJIMZqNQJFVpkuw";
pub const PS256_2048: &'static str = "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9. ";
pub const PS256_4096: &'static str = "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9. ";
pub const PS384_2048: &'static str = "eyJhbGciOiJQUzM4NCIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9. ";
pub const PS384_4096: &'static str = "eyJhbGciOiJQUzM4NCIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9. ";
pub const PS512_2048: &'static str = "eyJhbGciOiJQUzUxMiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9. ";
pub const PS512_4096: &'static str = "eyJhbGciOiJQUzUxMiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9. ";
pub const RS256_2048: &'static str = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.\
dzhXIZsJRP0_YzFkgHm_G4r-XwIyvffdUe6fmZiaPMnbDm0H_FQtNyLkMCnDJob2qbGxbfEQLLF7O4-Xrh0mUDFn7XlLfL\
d_22ZVemaqG0B9tPOVAFMxknjOFWSRpG35Lqvw0F4FySHUcK27nIi4nuHA2SvulvdQMtQbXNNw3umdiA32cIQYfr13WNOMC\
68cuDIlHn0OnQQWeRlYPHQZj53U-v57WczBVGUvK5UaZEgORJrh8mBV8KznpDvDXhKsJ8BJWom8Yp-r4gD0DNcfQnCEkk72\
WDWzRFIT2Q48lFbTBqkUgS4SCQ66zW7kz4DUFmVvfz39WrCBTkYqS81F7w";
pub const RS256_4096: &'static str = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.\
KncNhDRnGTTFQNyNnjXWLz95JGq6Zfj0fAYKc0tPqcj7Z5tYTdxXo8MpIGRhJf5OTRt6_aL2jPy4FCPcvaEnB2Bp4ohS07p\
724KnEkZF4wj0WCU7y6FVSbim-k3-UCjAPTPDzRxHC4fL9as4-bVOFs6RFTJPVKyj_uDrC0Tk43ueZUX3J3sFhEJyC4OZ9j\
MVy8tT7cU7R2-qM-hBXDO-fMgm3Ijmpa4q34VsL8GDMtLpT2CyoDxd-n92024VWhrY3drMCJD3gAy_O6UgBHVr_dfNF8att\
or2VNBzqfwjLJ6B_HWhrrGjlzDYHqAZBmXMq-SJtPuUu6VYku2H2tnvs1MOUkBWFICLlAvkyLAy6gB-QBoSZgJdlhIYarUa\
kJ8rKXs4Wjo98N47MAei7sM2RzrL7zMz0fIPqQhL5Y49rQW_yV2BCg7hUCwAcH6wzhgqAEXdgJigacPMCHNfbaqmJSc01JE\
Uzi0dWX5dH8wLAQG79-Ue0sXPelM-pemvSgKUr-FLrG3j2-0r8-oGpqblPN-5SQBScNEIwonozZFuDMn5nSaaWLvxDWV9C8\
T9TfcTh4A8ZIXpt2A0UsjXS1fWYtOSMIwkS_j3ILCL__Wj5iABls4nPFQOGOd_LTXEjiS4obyBaLPtGCT-s1qA13-1-miA8\
wshJaY60M-bKPyNJyM";
pub const RS384_2048: &'static str = "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.\
YUrcB6d8nanRt1VS6YQUzjtLPxCJeqJPkk2DEtINrweltrjD-kThdhOPGtiCWSE9XIkD7TtX9X01ucdsKZlUW31aPmPa08p\
CZK0eJ9u0r10OEZz4pyGn9xCPFgRU4di7OKQmnbMu9ufnFig5dZNh8DLyn1YHWecYFv4kAaaWiF7x8ygUkbUxA8ugXHY2g9\
qC5Oit8BHbe4FgNOeszvTBGEIiH9T1c7OepwSeGKXqb98n3zWAox_MPOTOvYGzljx_3HutHkmXiC2d3rgr8fiS9XDpqbv-l\
kMX8eBXOeKjjzsWB7qcF4ZK53btMwzhy6sHkNe6wFFqSCCe7yDzh-ugbA";
pub const RS384_4096: &'static str = "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.\
lsfKu9H1rPtc1gmPfFUTj9LjuxT_apUlk1MuoYMwerMPnBzjblAKZsgmC-S6inMblkFiFhriZ_5sRNXtZB0etKCM4Ea53YF\
5J8H5_7JBAtwv6OL0hZTxV4RvGMuVoaTJAmDD7S1Y6mdrGjWpuyIoOuAQ0eJh9RiWfMgX7eqeuPRd3Ti09pcxgh_zdbPcsR\
BybSrVgMQBfcyOMyzJq6irG4IS97p-ka6BIqJ7Lw1pgtV2USs7fbyoEkaEriXQzX7pppjce0lZVWbZ0uoiJXi2wypK3nNK6\
kd7bmphJ7B2pieU74c5hCZ75uoAm26lOX40XT86FAz0XS7Go3CFJK2PbWdte6Tesc-Xk1ghktG2x5tJy0tkMiwYX955iro4\
sl44ZT0cXhWEYdxw5yyJFoboeg1Uk5lmrEMB9UrwWvxpC0C7JOy95tojjpImUJgU62U7UebZn-XrNOduAOYlMXJiJ4a7vwN\
blWIoTkgWuIlTrNy2SzTf8X5gvb67Nc9DjV0nJRfhuNnd_IcwVfG61Vdb13FekG4TsVWbkItRG2l6_MPOQDYXF91hg7xWAm\
SK2WJazK4FI9G1_L4Np9LjSvbQ_AFTKffcFPyWdJiJef0vH6vk7P0W0Ea-T8RCQS8_NuA0Cx12zhICXPUyw4Rj3SySTVbwh\
aPjDrB0cgtNXlWYOWY";
pub const RS512_2048: &'static str = "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.\
G3HMiEggAaMlswaWMcWp71-fFJ_8FFbBvyx_AMLolbnnbbYXyT9T1y_481OVOYRx95xhZY_iXHlrIdb4Dfu3jqbp59J67ti\
LcAZF6xzNz5_bWTeXAMRhkF-RsnQBew-Dmy5tPgLhwERnXWNNWXCtlxi7JLm-ZAbcQwDmpvuWZj4Wwsc197uTfftS_tLMhX\
M2nAaQgie57sN59mm-YxQrGwHhroA2GPB9UzJ_orntbVRG2PcDQeNhnDzckSsn2TsrvLMne-KUzYmt8yoFd0DikQZEhGlaV\
OLtvoFSnEKU254YdvS7SKE7l1HkY_irfWDBxpDwFYyXg_gxan5Wwozatg";
pub const RS512_4096: &'static str = "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.\
S5ccfJeLu5sBWjYwBsw0Ccb16vEyDEFXn-drBRp8k6aoA1U5Lp2CUuZWKzNiHb66OSjQb-o-Vdd5FBODxZevJa2pn4KCO0Z\
0PD00c2aqT0-1Ail0DHgHZL4xqZOOJ4ysvaX3fUzzT-tAEaywkfFQS6VKOBkToiFFgMlKZUowxbpEqJrFFYSkrEIVvGSgYF\
tNBysylEUk82Q8Go5WY7MVzd-knhcvuz6Ko3sesvDFQEiIqrEYoll5oQERJ-a4FlLfOsi0FlkG6-96BdgMyG_gjKnL74wUP\
cAhWkylqP9a0y3eLmazPezudaTTqf3CzfuC1I9nopBcweXeVWKJcz1lkdDdMj8Ht1_VbWzxzRQQdgo4QIlWGJSuieOBJLHf\
2mH2aJqDcggez5OUnU1YUGIntfs3ce4-leYb77K_lVPI6BpzF6CSIJKadOxnx2aUkz54WlL7f471JcVAEpTYbihqAu-rhIY\
YjLASRKb0Zq5wWYqjQYW1KWZ8-p97zlDqYQe4cZNHeIRYqTszdBR8oP8fkl-C8QNk7YDRZ7F1OiDUgUPgqy_TBmm6cjvHiq\
00qqzGcgF-a3nmq25ZMPi0-bEYh4qxsqK1k9JNBqj5DO8fQ1ftdEbgNfo6SwB-XZaM4zxREoZwHIe6D1sFLHcCyt1rvSmZk\
41TOUnU0WIBOK98qu8";
pub const ISS_ONLY: &'static str = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJpc3MiOiJlbGxtYWsuaW8ifQ.\
6OOeJ0wqExhY-_UqHJfeMPDlzMFoZLm2-ce8YnQmvyQ";
#[derive(Clone, Deserialize, Serialize)]
pub struct Claims {
pub sub: String,
pub name: String,
pub admin: bool,
}
}