use crate::engine::raw::parse_header_json;
use crate::engine::shared_config::SharedVerifyConfig;
use crate::engine::shared_error::SharedAuthError;
use crate::KeySet;
const ALLOWED_HEADER_PARAMS: &[&str] = &["typ", "alg", "kid"];
pub(crate) fn run(
token: &str,
cfg: &SharedVerifyConfig,
key_set: &KeySet,
) -> Result<(), SharedAuthError> {
let header = parse_header_json(token)?;
if header.get("jku").is_some() {
return Err(SharedAuthError::HeaderJku);
}
if header.get("x5u").is_some() {
return Err(SharedAuthError::HeaderX5u);
}
if header.get("jwk").is_some() {
return Err(SharedAuthError::HeaderJwk);
}
if header.get("x5c").is_some() {
return Err(SharedAuthError::HeaderX5c);
}
if header.get("crit").is_some() {
return Err(SharedAuthError::HeaderCrit);
}
if let Some(cty) = header.get("cty").and_then(|v| v.as_str())
&& (cty.eq_ignore_ascii_case("jwt") || cty.eq_ignore_ascii_case("jose"))
{
return Err(SharedAuthError::NestedJws);
}
if header.get("b64") == Some(&serde_json::Value::Bool(false)) {
return Err(SharedAuthError::HeaderB64False);
}
if let Some(obj) = header.as_object() {
for key in obj.keys() {
if !ALLOWED_HEADER_PARAMS.contains(&key.as_str()) {
return Err(SharedAuthError::HeaderExtraParam);
}
}
}
let typ = header.get("typ").and_then(|v| v.as_str());
if typ != Some(cfg.expected_typ) {
return Err(SharedAuthError::TypMismatch);
}
let kid = header
.get("kid")
.and_then(|v| v.as_str())
.ok_or(SharedAuthError::KidUnknown)?;
if key_set.get(kid).is_none() {
return Err(SharedAuthError::KidUnknown);
}
Ok(())
}