rust_cfzt_validator/
app_token.rs1use crate::{
2 errors::{UnpackError, UnpackResult},
3 unpack, DecodedToken,
4};
5
6pub struct ApplicationToken {
8 pub email: String,
9 pub exp: u64,
10 pub iat: u64,
11 pub nbf: u64,
12 pub iss: String,
13 pub sub: String,
14 pub country: String,
15 pub custom: unpack::JsonObject,
16 pub headers: jsonwebtoken::Header,
17}
18
19impl ApplicationToken {
20 pub fn from_token_data(token_data: DecodedToken) -> UnpackResult<Self> {
23 let claims = unpack::as_object(&token_data.claims)?;
24
25 let get_str_claim = |key: &str| -> UnpackResult<String> {
26 Ok(unpack::as_string(unpack::get_key(claims, key)?)?.clone())
27 };
28
29 let get_uint_claim = |key: &str| -> UnpackResult<u64> {
30 let num = unpack::as_number(unpack::get_key(claims, key)?)?;
31 num.as_u64().ok_or(UnpackError::number_parse_failure("u64"))
32 };
33
34 let get_obj_claim = |key: &str| -> UnpackResult<unpack::JsonObject> {
35 Ok(unpack::as_object(unpack::get_key(claims, key)?)?.to_owned())
36 };
37
38 Ok(ApplicationToken {
39 email: get_str_claim("email")?,
40 exp: get_uint_claim("exp")?,
41 iat: get_uint_claim("iat")?,
42 nbf: get_uint_claim("nbf")?,
43 iss: get_str_claim("iss")?,
44 sub: get_str_claim("sub")?,
45 country: get_str_claim("country")?,
46 custom: get_obj_claim("custom")?,
47 headers: token_data.header,
48 })
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55 use crate::{
56 api::TeamKeys,
57 {TeamValidator, Validator},
58 };
59
60 const TEAM_NAME: &str = "molten";
61 const AUDIENCE: &str = "41f1d879c797d912d9bd80710db3dce92d30602a2dcbdf7bab33913071c44bd4";
62 const APPLICATION_TOKEN_JWT: &str = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImE1ZWE4YmQxYjk0Y2FkZjJhNWYwZjQ3ZGFkMTg4ZTZhYWZiY2QyOGVlYWIyZTcxYjExZGRkOTZkOWNjMjhjNjkifQ.eyJhdWQiOlsiNDFmMWQ4NzljNzk3ZDkxMmQ5YmQ4MDcxMGRiM2RjZTkyZDMwNjAyYTJkY2JkZjdiYWIzMzkxMzA3MWM0NGJkNCJdLCJlbWFpbCI6Im1lQGphY29idGF5bG9yLmlkLmF1IiwiZXhwIjoxNzE3OTgxNDM5LCJpYXQiOjE3MTc5Nzk2MzksIm5iZiI6MTcxNzk3OTYzOSwiaXNzIjoiaHR0cHM6Ly9tb2x0ZW4uY2xvdWRmbGFyZWFjY2Vzcy5jb20iLCJ0eXBlIjoiYXBwIiwiaWRlbnRpdHlfbm9uY2UiOiJBUFhHRnFsT2k5OVNsVVF3Iiwic3ViIjoiNzIwOGVlYTQtNDA5OC01YTMxLTkwNTMtZjA5YjgxYzI4MWZkIiwiY3VzdG9tIjp7ImVtYWlsIjoiIn0sImNvdW50cnkiOiJBVSJ9.nwTTyb2ioh5Fw39zKyBMZJuj0wzxOuP2KxsbzDLQCmOBNekTvhmquAui3bmuwpzhTTfjxP9yAJG1_N0Hmc-h613E8jOQclqAVgr9_JEYPZ2v58exPRgjeokEIQweRYKgLgoqHAqaYTKQ4v8-pHeRL66L-2Ui3uVUi8V8PkeJogKfPHvFjnkCqZPFFpuxkW735x0Vxq5CzQesoHH37hLAJe7ckc4Jav1AholNsLOvlBIxZtC9ET8-3YqO5rOUCqSX_6oKmf0VyOmqzbSw4gaXvnaTBAPiGruU63gg_LsV0NVGeVvddy84Tl3WvQvbPwdCJ9W9KsbkyOryfgbL0lrZPA";
63 const SIGNING_KEYS_JSON: &str = include_str!("../test_data/sample_signing_keys.json");
64
65 fn get_validator() -> Box<dyn Validator> {
66 let agent = ureq::agent();
67 let keys = TeamKeys::from_str(TEAM_NAME, SIGNING_KEYS_JSON).unwrap();
68 let validator = TeamValidator::from_team_keys(keys, agent);
69 Box::new(validator)
70 }
71
72 #[test]
73 fn test_application_token() {
74 let validator = get_validator();
75
76 let mut constraints = jsonwebtoken::Validation::new(jsonwebtoken::Algorithm::RS256);
77 constraints.validate_nbf = false;
78 constraints.validate_exp = false;
79 constraints.set_audience(&[AUDIENCE]);
80
81 let result = validator.validate_token(APPLICATION_TOKEN_JWT, TEAM_NAME, &mut constraints);
82 assert!(result.is_ok());
83
84 let app_token = ApplicationToken::from_token_data(result.unwrap()).unwrap();
85
86 assert_eq!(app_token.exp, 1717981439);
87 assert_eq!(app_token.iat, 1717979639);
88 assert_eq!(app_token.nbf, 1717979639);
89 assert_eq!(app_token.iss, "https://molten.cloudflareaccess.com");
90 assert_eq!(app_token.sub, "7208eea4-4098-5a31-9053-f09b81c281fd");
91 assert_eq!(app_token.country, "AU")
92 }
93}