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