Skip to content

Commit

Permalink
bug: pass settings to vapid when processing subscription request (#771)
Browse files Browse the repository at this point in the history
Closes: #770
  • Loading branch information
jrconlin authored Sep 30, 2024
1 parent 9afbe42 commit 3cc5a56
Showing 1 changed file with 44 additions and 40 deletions.
84 changes: 44 additions & 40 deletions autoendpoint/src/extractors/subscription.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ impl FromRequest for Subscription {

// Validate the VAPID JWT token and record the version
if let Some(vapid) = &vapid {
validate_vapid_jwt(vapid, &app_state.settings.endpoint_url(), &metrics)?;
validate_vapid_jwt(vapid, &app_state.settings, &metrics)?;

app_state
.metrics
Expand Down Expand Up @@ -286,10 +286,9 @@ fn term_to_label(term: &str) -> String {
/// This is mostly taken care of by the jsonwebtoken library
fn validate_vapid_jwt(
vapid: &VapidHeaderWithKey,
domain: &Url,
settings: &Settings,
metrics: &Metrics,
) -> ApiResult<()> {
let settings = Settings::with_env_and_config_file(&None).unwrap();
let VapidHeaderWithKey { vapid, public_key } = vapid;

let public_key = decode_public_key(public_key)?;
Expand Down Expand Up @@ -332,6 +331,9 @@ fn validate_vapid_jwt(
// the Json parse error.
return Err(VapidError::InvalidVapid(e.to_string()).into());
}
jsonwebtoken::errors::ErrorKind::InvalidAudience => {
return Err(VapidError::InvalidAudience.into());
}
_ => {
// Attempt to match up the majority of ErrorKind variants.
// The third-party errors all defer to the source, so we can
Expand Down Expand Up @@ -396,6 +398,8 @@ fn validate_vapid_jwt(
}
};

let domain = &settings.endpoint_url();

if domain != &aud {
info!(
"Bad Aud: I am <{:?}>, asked for <{:?}> ",
Expand All @@ -416,11 +420,11 @@ pub mod tests {
use crate::extractors::subscription::repad_base64;
use crate::headers::vapid::{VapidError, VapidHeader, VapidHeaderWithKey, VapidVersionData};
use crate::metrics::Metrics;
use crate::settings::Settings;

use autopush_common::util::b64_decode_std;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use url::Url;

pub const PUB_KEY: &str =
"BM3bVjW_wuZC54alIbqjTbaBNtthriVtdZlchOyOSdbVYeYQu2i5inJdft7jUWIAy4O9xHBbY196Gf-1odb8hds";
Expand Down Expand Up @@ -472,34 +476,38 @@ pub mod tests {
// Specify a potentially invalid padding.
let public_key = "BM3bVjW_wuZC54alIbqjTbaBNtthriVtdZlchOyOSdbVYeYQu2i5inJdft7jUWIAy4O9xHBbY196Gf-1odb8hds==".to_owned();
let domain = "https://push.services.mozilla.org";
let test_settings = Settings {
endpoint_url: domain.to_owned(),
..Default::default()
};

let header = make_vapid(
"mailto:[email protected]",
domain,
VapidClaims::default_exp() - 100,
public_key,
);
let result = validate_vapid_jwt(&header, &Url::from_str(domain).unwrap(), &Metrics::noop());
let result = validate_vapid_jwt(&header, &test_settings, &Metrics::noop());
assert!(result.is_ok());
}

#[test]
fn vapid_aud_invalid() {
let domain = "https://push.services.mozilla.org";
let test_settings = Settings {
endpoint_url: domain.to_owned(),
..Default::default()
};
let header = make_vapid(
"mailto:[email protected]",
domain,
"https://example.com",
VapidClaims::default_exp() - 100,
PUB_KEY.to_owned(),
);
assert!(matches!(
validate_vapid_jwt(
&header,
&Url::from_str("http://example.org").unwrap(),
&Metrics::noop()
)
.unwrap_err()
.kind,
validate_vapid_jwt(&header, &test_settings, &Metrics::noop())
.unwrap_err()
.kind,
ApiErrorKind::VapidError(VapidError::InvalidAudience)
));
}
Expand All @@ -514,6 +522,10 @@ pub mod tests {
}

let domain = "https://push.services.mozilla.org";
let test_settings = Settings {
endpoint_url: "domain".to_owned(),
..Default::default()
};
let jwk_header = jsonwebtoken::Header::new(jsonwebtoken::Algorithm::ES256);
let enc_key = jsonwebtoken::EncodingKey::from_ec_der(&PRIV_KEY);
let claims = StrExpVapidClaims {
Expand All @@ -530,13 +542,9 @@ pub mod tests {
version_data: VapidVersionData::Version1,
},
};
let vv = validate_vapid_jwt(
&header,
&Url::from_str("http://example.org").unwrap(),
&Metrics::noop(),
)
.unwrap_err()
.kind;
let vv = validate_vapid_jwt(&header, &test_settings, &Metrics::noop())
.unwrap_err()
.kind;
assert!(matches![
vv,
ApiErrorKind::VapidError(VapidError::InvalidVapid(_))
Expand All @@ -556,6 +564,10 @@ pub mod tests {
let public_key_standard = "BM3bVjW/wuZC54alIbqjTbaBNtthriVtdZlchOyOSdbVYeYQu2i5inJdft7jUWIAy4O9xHBbY196Gf+1odb8hds=".to_owned();
let public_key_url_safe = "BM3bVjW_wuZC54alIbqjTbaBNtthriVtdZlchOyOSdbVYeYQu2i5inJdft7jUWIAy4O9xHBbY196Gf-1odb8hds=".to_owned();
let domain = "https://push.services.mozilla.org";
let test_settings = Settings {
endpoint_url: domain.to_owned(),
..Default::default()
};
let jwk_header = jsonwebtoken::Header::new(jsonwebtoken::Algorithm::ES256);
let enc_key = jsonwebtoken::EncodingKey::from_ec_der(&PRIV_KEY);
let claims = VapidClaims {
Expand All @@ -573,9 +585,7 @@ pub mod tests {
version_data: VapidVersionData::Version1,
},
};
assert!(
validate_vapid_jwt(&header, &Url::from_str(domain).unwrap(), &Metrics::noop()).is_ok()
);
assert!(validate_vapid_jwt(&header, &test_settings, &Metrics::noop()).is_ok());
// try standard form with no padding
let header = VapidHeaderWithKey {
public_key: public_key_standard.trim_end_matches('=').to_owned(),
Expand All @@ -585,9 +595,7 @@ pub mod tests {
version_data: VapidVersionData::Version1,
},
};
assert!(
validate_vapid_jwt(&header, &Url::from_str(domain).unwrap(), &Metrics::noop()).is_ok()
);
assert!(validate_vapid_jwt(&header, &test_settings, &Metrics::noop()).is_ok());
// try URL safe form with padding
let header = VapidHeaderWithKey {
public_key: public_key_url_safe.clone(),
Expand All @@ -597,9 +605,7 @@ pub mod tests {
version_data: VapidVersionData::Version1,
},
};
assert!(
validate_vapid_jwt(&header, &Url::from_str(domain).unwrap(), &Metrics::noop()).is_ok()
);
assert!(validate_vapid_jwt(&header, &test_settings, &Metrics::noop()).is_ok());
// try URL safe form without padding
let header = VapidHeaderWithKey {
public_key: public_key_url_safe.trim_end_matches('=').to_owned(),
Expand All @@ -609,9 +615,7 @@ pub mod tests {
version_data: VapidVersionData::Version1,
},
};
assert!(
validate_vapid_jwt(&header, &Url::from_str(domain).unwrap(), &Metrics::noop()).is_ok()
);
assert!(validate_vapid_jwt(&header, &test_settings, &Metrics::noop()).is_ok());
}

#[test]
Expand All @@ -624,6 +628,10 @@ pub mod tests {
}

let domain = "https://push.services.mozilla.org";
let test_settings = Settings {
endpoint_url: domain.to_owned(),
..Default::default()
};
let jwk_header = jsonwebtoken::Header::new(jsonwebtoken::Algorithm::ES256);
let enc_key = jsonwebtoken::EncodingKey::from_ec_der(&PRIV_KEY);
let claims = NoSubVapidClaims {
Expand All @@ -640,13 +648,9 @@ pub mod tests {
version_data: VapidVersionData::Version1,
},
};
let vv = validate_vapid_jwt(
&header,
&Url::from_str("http://example.org").unwrap(),
&Metrics::noop(),
)
.unwrap_err()
.kind;
let vv = validate_vapid_jwt(&header, &test_settings, &Metrics::noop())
.unwrap_err()
.kind;
assert!(matches![
vv,
ApiErrorKind::VapidError(VapidError::InvalidVapid(_))
Expand Down

0 comments on commit 3cc5a56

Please sign in to comment.