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 124 125 126
//! 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; //! # extern crate chrono; //! # #[macro_use] extern crate serde_derive; //! # //! # use asap::claims::{DefaultClaims, Aud}; //! # use asap::generator::Generator; //! # use serde::de::DeserializeOwned; //! # use chrono::Utc; //! # //! // 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 mut generator = Generator::new(iss, kid, private_key); //! //! // Generate tokens, etc... //! # let aud = Aud::One("aud".to_string()); //! # let extra_claims: Option<DefaultClaims> = 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; //! # extern crate chrono; //! # #[macro_use] extern crate serde_derive; //! # //! # use asap::validator::{Validator, ValidatorBuilder}; //! # use serde::de::DeserializeOwned; //! # use chrono::Utc; //! # //! # let now = Utc::now().timestamp(); //! # //! // Construct the ASAP validator: //! let keyserver = String::from("http://my-keyserver/"); //! let resource_server_audience = String::from("my-server"); //! let mut validator = Validator::builder(keyserver, resource_server_audience) //! .fallback_keyserver(String::from("http://my-fallback-keyserver/")) //! .build(); //! //! // Your expected jwt claims: //! #[derive(Debug, Serialize, Deserialize, PartialEq)] //! struct MyClaims { //! iat: i64, //! exp: i64, //! iss: String, //! aud: String, // or Vec<String> //! jti: String, //! } //! //! let asap_token = "<your-token-here>"; //! let whitelisted_issuers = vec!["list", "of", "authorized", "subjects"]; //! //! match validator.decode::<MyClaims>(asap_token, &whitelisted_issuers) { //! 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 failure; #[macro_use] extern crate failure_derive; extern crate jsonwebtoken as jwt; extern crate pem; extern crate rand; extern crate reqwest; extern crate serde; extern crate serde_json; #[macro_use] extern crate serde_derive; mod util; mod errors; pub mod claims; pub mod generator; pub mod validator;