asap/lib.rs
1//! This is a rust library for generating and validating ASAP tokens. It provides
2//! options for doing so that are compliant with the [ASAP specification](https://s2sauth.bitbucket.io/spec/).
3//!
4//! ASAP is a protocol that extends JWT. It does this so resource servers can be
5//! confident that incoming requests with signed ASAP tokens are indeed coming
6//! from the intended client. If you want to know more, see [the specification](https://s2sauth.bitbucket.io/spec/).
7//!
8//! Things to note about this ASAP library:
9//!
10//! * This library is *awesome*. If you use Rust and want ASAP, you should use this!
11//! * At the moment it only supports the `RS256` algorithm. This is the most used
12//! algorithm that ASAP uses, so there's been no need to implement any others.
13//! * The ASAP `Validator` struct can optionally detect duplicate `jti` nonces.
14//!
15//! This library aims to be fully compliant with the ASAP specification [found here](https://s2sauth.bitbucket.io/spec/).
16//! If you notice anything out of the ordinary, please don't hesitate to make a Issue
17//! or PR stating where it doesn't comply.
18//!
19//! This library also aims to be really simple to use! You should concentrate
20//! less on ASAP, and more on writing your client or service. If you spend too
21//! much time working with this library, then it's failed its purpose. Please
22//! make an Issue/PR telling us why, and we'll do our best to make it better.
23//!
24//! Here's a quick example of how you can generate tokens using this library:
25//!
26//! ```rust
27//! # extern crate asap;
28//! # extern crate serde;
29//! # #[macro_use] extern crate serde_json;
30//! #
31//! use asap::claims::Aud;
32//! use asap::generator::Generator;
33//!
34//! // The identifier of the service that issues the token (`iss`).
35//! let iss = "service01".to_string();
36//! // The key id (`kid`) of the public key in your keyserver.
37//! let kid = "service01/my-key-id".to_string();
38//! // The `private_key` used to sign each token.
39//! let private_key = include_bytes!("../support/keys/service01/1530402390-private.der").to_vec();
40//!
41//! // Here's your generator! 🎉
42//! let generator = Generator::new(iss, kid, private_key);
43//!
44//! // Generate tokens, etc...
45//! # let aud = Aud::One("aud".to_string());
46//! # let extra_claims = None;
47//! let token = generator.token(aud, extra_claims).unwrap();
48//! ```
49//!
50//! And here's another example of how you can validate tokens. This example
51//! requires the default `validator` feature:
52//!
53//! ```rust
54//! # extern crate asap;
55//! # extern crate serde;
56//! # #[macro_use] extern crate serde_json;
57//! #
58//! # #[cfg(feature = "validator")]
59//! # async fn validator_example() {
60//! # use serde::de::DeserializeOwned;
61//! use asap::claims::Claims;
62//! use asap::validator::Validator;
63//!
64//! let asap_token = "<your-asap-token>";
65//!
66//! // The keyserver(s) which hosts your public keys.
67//! let primary_keyserver = "http://my-keyserver/".to_string();
68//! let fallback_keyserver = "http://my-fallback-keyserver/".to_string();
69//! // The audience of the server/resource that validates the incoming tokens.
70//! let resource_server_audience = "my-server".to_string();
71//!
72//! // Build the ASAP validator:
73//! let validator = Validator::builder(primary_keyserver, resource_server_audience)
74//! .fallback_keyserver(fallback_keyserver)
75//! .build();
76//!
77//! // A list of issuers that are allowed to access this server/resource.
78//! let whitelisted_issuers = vec!["list", "of", "whitelisted", "issuers"];
79//! match validator.decode(asap_token, &whitelisted_issuers).await {
80//! Ok(token_data) => {
81//! // Here you have a successfully verified and accepted access token!
82//! //
83//! // Remember the directions from the ASAP spec:
84//! // If the resource server successfully verifies and accepts the
85//! // access token, then it MUST process the request and it MUST assume
86//! // that the request was issued by the issuer.
87//! println!("claims {:?}", token_data.claims);
88//! },
89//! Err(e) => {
90//! // Oh boo, there was an error decoding and validating the ASAP token.
91//! //
92//! // Remember the directions from the ASAP spec:
93//! // If the resource server rejects the access token, then it MUST
94//! // reply with a status code of 401 UNAUTHORIZED and MUST include a
95//! // WWW-Authenticate header field as per the HTTP specification.
96//! eprintln!("{:?}", e);
97//! }
98//! }
99//! # }
100//! ```
101//!
102//! That's really it! It should be simple - that's the goal.
103
104#[cfg(all(
105 feature = "validator",
106 not(any(feature = "generator", feature = "generator-fips"))
107))]
108compile_error!("the `validator` feature requires either `generator` or `generator-fips`");
109
110extern crate chrono;
111#[macro_use]
112extern crate anyhow;
113#[cfg(all(
114 any(feature = "generator", feature = "generator-fips"),
115 not(any(feature = "fips", feature = "generator-fips"))
116))]
117extern crate jsonwebtoken as jwt;
118#[cfg(any(feature = "fips", feature = "generator-fips"))]
119extern crate jsonwebtoken_aws_lc as jwt;
120extern crate lru_time_cache;
121extern crate pem;
122extern crate rand;
123#[cfg(feature = "validator")]
124extern crate reqwest;
125extern crate serde;
126#[cfg(feature = "validator")]
127extern crate thiserror;
128#[macro_use]
129extern crate serde_derive;
130#[macro_use]
131extern crate serde_json;
132
133pub mod claims;
134#[cfg(any(feature = "generator", feature = "generator-fips"))]
135mod errors;
136#[cfg(any(feature = "generator", feature = "generator-fips"))]
137pub mod generator;
138#[cfg(any(feature = "generator", feature = "generator-fips"))]
139mod util;
140#[cfg(feature = "validator")]
141pub mod validator;