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;