jwt_simple_legacy/lib.rs
1//! 
2//! [](https://docs.rs/jwt-simple/)
3//! [](https://crates.io/crates/jwt-simple)
4//!
5//! # JWT-Simple
6//!
7//! A new JWT implementation for Rust that focuses on simplicity, while avoiding
8//! common JWT security pitfalls.
9//!
10//! `jwt-simple` is unopinionated and supports all commonly deployed
11//! authentication and signature algorithms:
12//!
13//! * HMAC-SHA2:
14//! * `HS256`
15//! * `HS384`
16//! * `HS512`
17//! * RSA
18//! * `RS256`
19//! * `RS384`
20//! * `RS512`
21//! * `PS256`
22//! * `PS384`
23//! * `PS512`
24//! * p256
25//! * `ES256`
26//! * p384
27//! * `ES384`
28//! * secp256k1
29//! * `ES256K`
30//! * Ed25519
31//! * `EdDSA`
32//!
33//! `jwt-simple` uses only pure Rust implementations, and can be compiled out of
34//! the box to WebAssembly/WASI. It is fully compatible with Fastly's
35//! _Compute@Edge_ service.
36//!
37//! Important: JWT's purpose is to verify that data has been created by a party
38//! knowing a secret key. It does not provide any kind of confidentiality: JWT
39//! data is simply encoded as BASE64, and is not encrypted.
40//!
41//! ## Usage
42//!
43//! `cargo.toml`:
44//!
45//! ```toml
46//! [dependencies]
47//! jwt-simple = "0.10"
48//! ```
49//!
50//! Rust:
51//!
52//! ```rust
53//! use jwt_simple::prelude::*;
54//! ```
55//!
56//! ## Authentication (symmetric, `HS*` JWT algorithms) example
57//!
58//! Authentication schemes use the same key for creating and verifying tokens.
59//! In other words, both parties need to ultimately trust each other, or else
60//! the verifier could also create arbitrary tokens.
61//!
62//! ### Keys and tokens creation
63//!
64//! Key creation:
65//!
66//! ```rust
67//! use jwt_simple::prelude::*;
68//!
69//! // create a new key for the `HS256` JWT algorithm
70//! let key = HS256Key::generate();
71//! ```
72//!
73//! A key can be exported as bytes with `key.to_bytes()`, and restored with
74//! `HS256Key::from_bytes()`.
75//!
76//! Token creation:
77//!
78//! ```rust
79//! # use jwt_simple::prelude::*;
80//! # fn main() -> Result<(), jwt_simple::Error> {
81//! # let key = HS256Key::generate();
82//! /// create claims valid for 2 hours
83//! let claims = Claims::create(Duration::from_hours(2));
84//! let token = key.authenticate(claims)?;
85//! # Ok(()) }
86//! ```
87//!
88//! -> Done!
89//!
90//! ### Token verification
91//!
92//! ```rust
93//! # use jwt_simple::prelude::*;
94//! # fn main() -> Result<(), jwt_simple::Error> {
95//! # let key = HS256Key::generate();
96//! # let token = key.authenticate(Claims::create(Duration::from_secs(10)))?;
97//! let claims = key.verify_token::<NoCustomClaims>(&token, None)?;
98//! # Ok(()) }
99//! ```
100//!
101//! -> Done! No additional steps required.
102//!
103//! Key expiration, start time, authentication tags, etc. are automatically
104//! verified. The function fails with `JWTError::InvalidAuthenticationTag` if
105//! the authentication tag is invalid for the given key.
106//!
107//! The full set of claims can be inspected in the `claims` object if necessary.
108//! `NoCustomClaims` means that only the standard set of claims is used by the
109//! application, but application-defined claims can also be supported.
110//!
111//! Extra verification steps can optionally be enabled via the
112//! `ValidationOptions` structure:
113//!
114//! ```rust
115//! # use jwt_simple::prelude::*;
116//! # fn main() -> Result<(), jwt_simple::Error> {
117//! # let key = HS256Key::generate();
118//! # let token = key.authenticate(Claims::create(Duration::from_secs(10)).with_issuer("example app"))?;
119//! let mut options = VerificationOptions::default();
120//! // Accept tokens that will only be valid in the future
121//! options.accept_future = true;
122//! // Accept tokens even if they have expired up to 15 minutes after the deadline
123//! // and/or they will be valid within 15 minutes.
124//! options.time_tolerance = Some(Duration::from_mins(15));
125//! // Reject tokens if they were issued more than 1 hour ago
126//! options.max_validity = Some(Duration::from_hours(1));
127//! // Reject tokens if they don't include an issuer from that list
128//! options.allowed_issuers = Some(HashSet::from_strings(&["example app"]));
129//! // See the documentation for the full list of available options
130//!
131//! let claims = key.verify_token::<NoCustomClaims>(&token, Some(options))?;
132//! # Ok(()) }
133//! ```
134//!
135//! Note that `allowed_issuers` and `allowed_audiences` are not strings, but
136//! sets of strings (using the `HashSet` type from the Rust standard library),
137//! as the application can allow multiple return values.
138//!
139//! ## Signatures (asymmetric, `RS*`, `PS*`, `ES*` and `EdDSA` algorithms) example
140//!
141//! A signature requires a key pair: a secret key used to create tokens, and a
142//! public key, that can only verify them.
143//!
144//! Always use a signature scheme if both parties do not ultimately trust each
145//! other, such as tokens exchanged between clients and API providers.
146//!
147//! ### Key pairs and tokens creation
148//!
149//! Key creation:
150//!
151//! ```rust
152//! use jwt_simple::prelude::*;
153//!
154//! // create a new key pair for the `ES256` JWT algorithm
155//! let key_pair = ES256KeyPair::generate();
156//!
157//! // Or the `ES384` JWT algorithm
158//! let key_pair = ES384KeyPair::generate();
159//!
160//! // a public key can be extracted from a key pair:
161//! let public_key = key_pair.public_key();
162//! ```
163//!
164//! Keys can be exported as bytes for later reuse, and imported from bytes or,
165//! for RSA, from individual parameters, DER-encoded data or PEM-encoded data.
166//!
167//! RSA key pair creation, using OpenSSL and PEM importation of the secret key:
168//!
169//! ```sh
170//! openssl genrsa -out private.pem 2048
171//! openssl rsa -in private.pem -outform PEM -pubout -out public.pem
172//! ```
173//!
174//! ```no_run
175//! # use jwt_simple::prelude::*;
176//! # fn main() -> Result<(), jwt_simple::Error> {
177//! # let private_pem_file_content = "";
178//! # let public_pem_file_content = "";
179//! let key_pair = RS384KeyPair::from_pem(private_pem_file_content)?;
180//! let public_key = RS384PublicKey::from_pem(public_pem_file_content)?;
181//! # Ok(()) }
182//! ```
183//!
184//! Token creation and verification work the same way as with `HS*` algorithms,
185//! except that tokens are created with a key pair, and verified using the
186//! corresponding public key.
187//!
188//! Token creation:
189//!
190//! ```rust
191//! # use jwt_simple::prelude::*;
192//! # fn main() -> Result<(), jwt_simple::Error> {
193//! # let key_pair = Ed25519KeyPair::generate();
194//! /// create claims valid for 2 hours
195//! let claims = Claims::create(Duration::from_hours(2));
196//! let token = key_pair.sign(claims)?;
197//! # Ok(()) }
198//! ```
199//!
200//! Token verification:
201//!
202//! ```rust
203//! # use jwt_simple::prelude::*;
204//! # fn main() -> Result<(), jwt_simple::Error> {
205//! # let key_pair = Ed25519KeyPair::generate();
206//! # let public_key = key_pair.public_key();
207//! # let token = key_pair.sign(Claims::create(Duration::from_secs(10)))?;
208//! let claims = public_key.verify_token::<NoCustomClaims>(&token, None)?;
209//! # Ok(()) }
210//! ```
211//!
212//! Available verification options are identical to the ones used with symmetric
213//! algorithms.
214//!
215//! ## Advanced usage
216//!
217//! ### Custom claims
218//!
219//! Claim objects support all the standard claims by default, and they can be
220//! set directly or via convenient helpers:
221//!
222//! ```rust
223//! # use jwt_simple::prelude::*;
224//! let claims = Claims::create(Duration::from_hours(2))
225//! .with_issuer("Example issuer")
226//! .with_subject("Example subject");
227//! ```
228//!
229//! But application-defined claims can also be defined. These simply have to be
230//! present in a serializable type (this requires the `serde` crate):
231//!
232//! ```rust
233//! # use jwt_simple::prelude::*;
234//! # fn main() -> Result<(), jwt_simple::Error> {
235//! #[derive(Serialize, Deserialize)]
236//! struct MyAdditionalData {
237//! user_is_admin: bool,
238//! user_country: String,
239//! }
240//! let my_additional_data = MyAdditionalData {
241//! user_is_admin: false,
242//! user_country: "FR".to_string(),
243//! };
244//!
245//! // Claim creation with custom data:
246//!
247//! # use jwt_simple::prelude::*;
248//! let claims = Claims::with_custom_claims(my_additional_data, Duration::from_secs(30));
249//!
250//! // Claim verification with custom data. Note the presence of the custom data type:
251//!
252//! # let key_pair = Ed25519KeyPair::generate();
253//! # let public_key = key_pair.public_key();
254//! # let token = key_pair.sign(claims)?;
255//! let claims = public_key.verify_token::<MyAdditionalData>(&token, None)?;
256//! let user_is_admin = claims.custom.user_is_admin;
257//! # Ok(()) }
258//! ```
259//!
260//! ### Peeking at metadata before verification
261//!
262//! Properties such as the key identifier can be useful prior to tag or
263//! signature verification in order to pick the right key out of a set.
264//!
265//! ```rust
266//! # use jwt_simple::prelude::*;
267//! # fn main() -> Result<(), jwt_simple::Error> {
268//! # let token = Ed25519KeyPair::generate().sign(Claims::create(Duration::from_hours(2)))?;
269//! let metadata = Token::decode_metadata(&token)?;
270//! let key_id = metadata.key_id();
271//! let algorithm = metadata.algorithm();
272//! // all other standard properties are also accessible
273//! # Ok(()) }
274//! ```
275//!
276//! ### Creating and attaching key identifiers
277//!
278//! Key identifiers indicate to verifiers what public key (or shared key) should
279//! be used for verification. They can be attached at any time to existing
280//! shared keys, key pairs and public keys:
281//!
282//! ```rust
283//! # use jwt_simple::prelude::*;
284//! # let public_key = Ed25519KeyPair::generate().public_key();
285//! let public_key_with_id = public_key.with_key_id(&"unique key identifier");
286//! ```
287//!
288//! Instead of delegating this to applications, `jwt-simple` can also create
289//! such an identifier for an existing key:
290//!
291//! ```rust
292//! # use jwt_simple::prelude::*;
293//! # let mut public_key = Ed25519KeyPair::generate().public_key();
294//! let key_id = public_key.create_key_id();
295//! ```
296//!
297//! This creates an text-encoded identifier for the key, attaches it, and
298//! returns it.
299//!
300//! If an identifier has been attached to a shared key or a key pair, tokens
301//! created with them will include it.
302
303#![forbid(unsafe_code)]
304
305pub mod algorithms;
306pub mod claims;
307pub mod common;
308#[cfg(feature = "cwt")]
309pub mod cwt_token;
310pub mod token;
311
312mod jwt_header;
313mod serde_additions;
314
315pub mod reexports {
316 pub use anyhow;
317 pub use coarsetime;
318 pub use ct_codecs;
319 pub use rand;
320 pub use serde;
321 pub use serde_json;
322 pub use thiserror;
323 pub use zeroize;
324}
325
326mod error;
327pub use error::{Error, JWTError};
328
329pub mod prelude {
330 pub use std::collections::HashSet;
331
332 pub use coarsetime::{self, Clock, Duration, UnixTimeStamp};
333 pub use ct_codecs::{
334 Base64, Base64NoPadding, Base64UrlSafe, Base64UrlSafeNoPadding, Decoder as _, Encoder as _,
335 };
336 pub use serde::{Deserialize, Serialize};
337
338 pub use crate::algorithms::*;
339 pub use crate::claims::*;
340 pub use crate::common::*;
341 #[cfg(feature = "cwt")]
342 pub use crate::cwt_token::*;
343 pub use crate::token::*;
344
345 mod hashset_from_strings {
346 use std::collections::HashSet;
347
348 pub trait HashSetFromStringsT {
349 /// Create a set from a list of strings
350 fn from_strings(strings: &[impl ToString]) -> HashSet<String> {
351 strings.iter().map(|x| x.to_string()).collect()
352 }
353 }
354
355 impl HashSetFromStringsT for HashSet<String> {}
356 }
357
358 pub use hashset_from_strings::HashSetFromStringsT as _;
359}
360
361#[cfg(test)]
362mod tests {
363 use crate::prelude::*;
364
365 const RSA_KP_PEM: &str = r"
366-----BEGIN RSA PRIVATE KEY-----
367MIIEpAIBAAKCAQEAyqq0N5u8Jvl+BLH2VMP/NAv/zY9T8mSq0V2Gk5Ql5H1a+4qi
3683viorUXG3AvIEEccpLsW85ps5+I9itp74jllRjA5HG5smbb+Oym0m2Hovfj6qP/1
369m1drQg8oth6tNmupNqVzlGGWZLsSCBLuMa3pFaPhoxl9lGU3XJIQ1/evMkOb98I3
370hHb4ELn3WGtNlAVkbP20R8sSii/zFjPqrG/NbSPLyAl1ctbG2d8RllQF1uRIqYQj
37185yx73hqQCMpYWU3d9QzpkLf/C35/79qNnSKa3t0cyDKinOY7JGIwh8DWAa4pfEz
372gg56yLcilYSSohXeaQV0nR8+rm9J8GUYXjPK7wIDAQABAoIBAQCpeRPYyHcPFGTH
3734lU9zuQSjtIq/+bP9FRPXWkS8bi6GAVEAUtvLvpGYuoGyidTTVPrgLORo5ncUnjq
374KwebRimlBuBLIR/Zboery5VGthoc+h4JwniMnQ6JIAoIOSDZODA5DSPYeb58n15V
375uBbNHkOiH/eoHsG/nOAtnctN/cXYPenkCfeLXa3se9EzkcmpNGhqCBL/awtLU17P
376Iw7XxsJsRMBOst4Aqiri1GQI8wqjtXWLyfjMpPR8Sqb4UpTDmU1wHhE/w/+2lahC
377Tu0/+sCWj7TlafYkT28+4pAMyMqUT6MjqdmGw8lD7/vXv8TF15NU1cUv3QSKpVGe
37850vlB1QpAoGBAO1BU1evrNvA91q1bliFjxrH3MzkTQAJRMn9PBX29XwxVG7/HlhX
3790tZRSR92ZimT2bAu7tH0Tcl3Bc3NwEQrmqKlIMqiW+1AVYtNjuipIuB7INb/TUM3
380smEh+fn3yhMoVxbbh/klR1FapPUFXlpNv3DJHYM+STqLMhl9tEc/I7bLAoGBANqt
381zR6Kovf2rh7VK/Qyb2w0rLJE7Zh/WI+r9ubCba46sorqkJclE5cocxWuTy8HWyQp
382spxzLP1FQlsI+MESgRLueoH3HtB9lu/pv6/8JlNjU6SzovfUZ0KztVUyUeB4vAcH
383pGcf2CkUtoYc8YL22Ybck3s8ThIdnY5zphCF55PtAoGAf46Go3c05XVKx78R05AD
384D2/y+0mnSGSzUjHPMzPyadIPxhltlCurlERhnwPGC4aNHFcvWTwS8kUGns6HF1+m
385JNnI1okSCW10UI/jTJ1avfwU/OKIBKKWSfi9cDJTt5cRs51V7pKnVEr6sy0uvDhe
386u+G091HuhwY9ak0WNtPwfJ8CgYEAuRdoyZQQso7x/Bj0tiHGW7EOB2n+LRiErj6g
387odspmNIH8zrtHXF9bnEHT++VCDpSs34ztuZpywnHS2SBoHH4HD0MJlszksbqbbDM
3881bk3+1bUIlEF/Hyk1jljn3QTB0tJ4y1dwweaH9NvVn7DENW9cr/aePGnJwA4Lq3G
389fq/IPlUCgYAuqgJQ4ztOq0EaB75xgqtErBM57A/+lMWS9eD/euzCEO5UzWVaiIJ+
390nNDmx/jvSrxA1Ih8TEHjzv4ezLFYpaJrTst4Mjhtx+csXRJU9a2W6HMXJ4Kdn8rk
391PBziuVURslNyLdlFsFlm/kfvX+4Cxrbb+pAGETtRTgmAoCDbvuDGRQ==
392-----END RSA PRIVATE KEY-----
393 ";
394
395 const RSA_PK_PEM: &str = r"
396-----BEGIN PUBLIC KEY-----
397MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyqq0N5u8Jvl+BLH2VMP/
398NAv/zY9T8mSq0V2Gk5Ql5H1a+4qi3viorUXG3AvIEEccpLsW85ps5+I9itp74jll
399RjA5HG5smbb+Oym0m2Hovfj6qP/1m1drQg8oth6tNmupNqVzlGGWZLsSCBLuMa3p
400FaPhoxl9lGU3XJIQ1/evMkOb98I3hHb4ELn3WGtNlAVkbP20R8sSii/zFjPqrG/N
401bSPLyAl1ctbG2d8RllQF1uRIqYQj85yx73hqQCMpYWU3d9QzpkLf/C35/79qNnSK
402a3t0cyDKinOY7JGIwh8DWAa4pfEzgg56yLcilYSSohXeaQV0nR8+rm9J8GUYXjPK
4037wIDAQAB
404-----END PUBLIC KEY-----
405 ";
406
407 #[test]
408 fn hs384() {
409 let key = HS384Key::from_bytes(b"your-256-bit-secret").with_key_id("my-key-id");
410 let claims = Claims::create(Duration::from_secs(86400)).with_issuer("test issuer");
411 let token = key.authenticate(claims).unwrap();
412 let options = VerificationOptions {
413 allowed_issuers: Some(HashSet::from_strings(&["test issuer"])),
414 ..Default::default()
415 };
416 let _claims = key
417 .verify_token::<NoCustomClaims>(&token, Some(options))
418 .unwrap();
419 }
420
421 #[test]
422 fn rs256() {
423 let key_pair = RS256KeyPair::from_pem(RSA_KP_PEM).unwrap();
424 let claims = Claims::create(Duration::from_secs(86400));
425 let token = key_pair.sign(claims).unwrap();
426 let pk = RS256PublicKey::from_pem(RSA_PK_PEM).unwrap();
427 let _claims = pk.verify_token::<NoCustomClaims>(&token, None).unwrap();
428 let components = pk.to_components();
429 let hex_e = Base64::encode_to_string(components.e).unwrap();
430 let _e = Base64::decode_to_vec(hex_e, None).unwrap();
431 }
432
433 #[test]
434 fn ps384() {
435 let key_pair = PS384KeyPair::generate(2048).unwrap();
436 let claims = Claims::create(Duration::from_secs(86400));
437 let token = key_pair.sign(claims).unwrap();
438 let _claims = key_pair
439 .public_key()
440 .verify_token::<NoCustomClaims>(&token, None)
441 .unwrap();
442 }
443
444 #[test]
445 fn es256() {
446 let key_pair = ES256KeyPair::generate();
447 let claims = Claims::create(Duration::from_secs(86400));
448 let token = key_pair.sign(claims).unwrap();
449 let _claims = key_pair
450 .public_key()
451 .verify_token::<NoCustomClaims>(&token, None)
452 .unwrap();
453 }
454
455 #[test]
456 fn es384() {
457 let key_pair = ES384KeyPair::generate();
458 let claims = Claims::create(Duration::from_secs(86400));
459 let token = key_pair.sign(claims).unwrap();
460 let _claims = key_pair
461 .public_key()
462 .verify_token::<NoCustomClaims>(&token, None)
463 .unwrap();
464 }
465
466 #[test]
467 fn es256k() {
468 let key_pair = ES256kKeyPair::generate();
469 let claims = Claims::create(Duration::from_secs(86400));
470 let token = key_pair.sign(claims).unwrap();
471 let _claims = key_pair
472 .public_key()
473 .verify_token::<NoCustomClaims>(&token, None)
474 .unwrap();
475 }
476
477 #[test]
478 fn ed25519() {
479 #[derive(Serialize, Deserialize)]
480 struct CustomClaims {
481 is_custom: bool,
482 }
483
484 let key_pair = Ed25519KeyPair::generate();
485 let mut pk = key_pair.public_key();
486 let key_id = pk.create_key_id();
487 let key_pair = key_pair.with_key_id(key_id);
488 let custom_claims = CustomClaims { is_custom: true };
489 let claims = Claims::with_custom_claims(custom_claims, Duration::from_secs(86400));
490 let token = key_pair.sign(claims).unwrap();
491 let options = VerificationOptions {
492 required_key_id: Some(key_id.to_string()),
493 ..Default::default()
494 };
495 let claims: JWTClaims<CustomClaims> = key_pair
496 .public_key()
497 .verify_token::<CustomClaims>(&token, Some(options))
498 .unwrap();
499 assert!(claims.custom.is_custom);
500 }
501
502 #[test]
503 fn ed25519_der() {
504 let key_pair = Ed25519KeyPair::generate();
505 let der = key_pair.to_der();
506 let key_pair2 = Ed25519KeyPair::from_der(&der).unwrap();
507 assert_eq!(key_pair.to_bytes(), key_pair2.to_bytes());
508 }
509
510 #[test]
511 fn require_nonce() {
512 let key = HS256Key::generate();
513 let mut claims = Claims::create(Duration::from_hours(1));
514 let nonce = claims.create_nonce();
515 let token = key.authenticate(claims).unwrap();
516
517 let options = VerificationOptions {
518 required_nonce: Some(nonce),
519 ..Default::default()
520 };
521 key.verify_token::<NoCustomClaims>(&token, Some(options))
522 .unwrap();
523 }
524
525 #[test]
526 fn eddsa_pem() {
527 let sk_pem = "-----BEGIN PRIVATE KEY-----
528MC4CAQAwBQYDK2VwBCIEIMXY1NUbUe/3dW2YUoKW5evsnCJPMfj60/q0RzGne3gg
529-----END PRIVATE KEY-----\n";
530 let pk_pem = "-----BEGIN PUBLIC KEY-----
531MCowBQYDK2VwAyEAyrRjJfTnhMcW5igzYvPirFW5eUgMdKeClGzQhd4qw+Y=
532-----END PUBLIC KEY-----\n";
533 let kp = Ed25519KeyPair::from_pem(sk_pem).unwrap();
534 assert_eq!(kp.public_key().to_pem(), pk_pem);
535 }
536
537 #[test]
538 fn key_metadata() {
539 let mut key_pair = Ed25519KeyPair::generate();
540 let thumbprint = key_pair.public_key().sha1_thumbprint();
541 let key_metadata = KeyMetadata::default()
542 .with_certificate_sha1_thumbprint(&thumbprint)
543 .unwrap();
544 key_pair.attach_metadata(key_metadata).unwrap();
545
546 let claims = Claims::create(Duration::from_secs(86400));
547 let token = key_pair.sign(claims).unwrap();
548
549 let decoded_metadata = Token::decode_metadata(&token).unwrap();
550 assert_eq!(
551 decoded_metadata.certificate_sha1_thumbprint(),
552 Some(thumbprint.as_ref())
553 );
554 let _ = key_pair
555 .public_key()
556 .verify_token::<NoCustomClaims>(&token, None)
557 .unwrap();
558 }
559
560 #[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
561 #[test]
562 fn expired_token() {
563 let key = HS256Key::generate();
564 let claims = Claims::create(Duration::from_secs(1));
565 let token = key.authenticate(claims).unwrap();
566 std::thread::sleep(std::time::Duration::from_secs(2));
567 let options = VerificationOptions {
568 time_tolerance: None,
569 ..Default::default()
570 };
571 let claims = key.verify_token::<NoCustomClaims>(&token, None);
572 assert!(claims.is_ok());
573 let claims = key.verify_token::<NoCustomClaims>(&token, Some(options));
574 assert!(claims.is_err());
575 }
576}