compact_jwt/lib.rs
1#![deny(warnings)]
2#![warn(missing_docs)]
3#![warn(unused_extern_crates)]
4#![forbid(unsafe_code)]
5// Enable some groups of clippy lints.
6#![deny(clippy::suspicious)]
7#![deny(clippy::perf)]
8// Specific lints to enforce.
9#![deny(clippy::todo)]
10#![deny(clippy::unimplemented)]
11#![deny(clippy::unwrap_used)]
12#![deny(clippy::expect_used)]
13#![deny(clippy::panic)]
14#![deny(clippy::await_holding_lock)]
15#![deny(clippy::needless_pass_by_value)]
16#![deny(clippy::trivially_copy_pass_by_ref)]
17#![deny(clippy::disallowed_types)]
18#![deny(clippy::manual_let_else)]
19#![allow(clippy::unreachable)]
20
21//! Json Web Tokens (JWT) are a popular method for creating signed transparent tokens that can be verified
22//! by clients and servers. They are enshrined in standards like OpenID Connect which causes them to
23//! be a widespread and required component of many modern web authentication system.
24//!
25//! This is a minimal implementation of JWTs and Oidc Tokens that aims for auditability and correctness.
26//!
27//! # Examples
28//! ```
29//! # {
30//! use std::str::FromStr;
31//! use std::convert::TryFrom;
32//! use std::time::SystemTime;
33//! use url::Url;
34//! use compact_jwt::{
35//! OidcToken,
36//! OidcSubject,
37//! OidcUnverified,
38//! JwsEs256Signer,
39//! // Traits
40//! JwsSigner,
41//! JwsSignerToVerifier,
42//! JwsVerifier,
43//! };
44//!
45//! let oidc = OidcToken {
46//! iss: Url::parse("https://oidc.example.com").expect("Failed to parse URL"),
47//! sub: OidcSubject::S("UniqueId".to_string()),
48//! # aud: "test".to_string(),
49//! # exp: 0,
50//! # nbf: Some(0),
51//! # iat: 0,
52//! # auth_time: Some(0),
53//! # nonce: None,
54//! # at_hash: None,
55//! # acr: None,
56//! # amr: None,
57//! # azp: None,
58//! # jti: None,
59//! # s_claims: Default::default(),
60//! # claims: Default::default(),
61//! };
62//!
63//! let mut jws_es256_signer =
64//! JwsEs256Signer::generate_es256().expect("Unable to generate ES256 signer");
65//!
66//! let oidc_signed = jws_es256_signer.sign(&oidc)
67//! .expect("Unable to sign OIDC token");
68//!
69//! // Get the signed formatted token string
70//! let token_str = oidc_signed.to_string();
71//!
72//! // Build a validator from the public key of the signer. In a client scenario
73//! // you would get this public jwk from the oidc authorisation server.
74//! let mut jwk_es256_verifier = jws_es256_signer
75//! .get_verifier()
76//! .expect("failed to get verifier from signer");
77//!
78//! // Assuming we have the token_str, we parse it to an unverified state.
79//! let oidc_unverified = OidcUnverified::from_str(&token_str)
80//! .expect("Unable to parse OIDC token");
81//!
82//! let curtime = SystemTime::now()
83//! .duration_since(SystemTime::UNIX_EPOCH)
84//! .expect("Failed to retrieve current time")
85//! .as_secs() as i64;
86//!
87//! let oidc_validated = jwk_es256_verifier
88//! .verify(&oidc_unverified)
89//! .and_then(|oidc_exp| oidc_exp.verify_exp(curtime))
90//! .expect("Unable to validate OIDC token");
91//!
92//! // Prove we got back the same content.
93//! assert!(oidc_validated == oidc);
94//! # }
95//! ```
96
97#[allow(unused_imports)]
98#[macro_use]
99extern crate tracing;
100
101pub mod crypto;
102
103#[cfg(feature = "unsafe_release_without_verify")]
104pub mod dangernoverify;
105
106pub mod compact;
107
108pub mod traits;
109
110pub mod error;
111pub mod jwe;
112pub mod jws;
113pub mod jwt;
114pub mod oidc;
115
116pub use crate::compact::{JwaAlg, JweCompact, Jwk, JwkKeySet, JwkUse, JwsCompact};
117pub use crate::crypto::{JwsEs256Signer, JwsEs256Verifier, JwsHs256Signer};
118pub use crate::error::JwtError;
119pub use crate::jws::{Jws, JwsSigned};
120pub use crate::jwt::{Jwt, JwtSigned, JwtUnverified};
121pub use crate::oidc::{OidcClaims, OidcSigned, OidcSubject, OidcToken, OidcUnverified};
122pub use crate::traits::{JwsSigner, JwsSignerToVerifier, JwsVerifier};
123
124// 96 bits is more than enough to uniquely ID a key
125const KID_LEN: usize = 12;
126
127pub(crate) fn btreemap_empty(
128 m: &std::collections::BTreeMap<String, serde_json::value::Value>,
129) -> bool {
130 m.is_empty()
131}
132
133pub(crate) fn vec_empty(m: &[String]) -> bool {
134 m.is_empty()
135}