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