feat: claim types

This commit is contained in:
2024-04-15 00:40:38 +08:00
parent e13503116a
commit 68473e2f01

View File

@@ -53,14 +53,25 @@ impl Command for CommandImpl {
..Default::default()
};
let mut jwt_claims = Map::new();
if let Some(payload) = payload {
match serde_json::from_str::<Value>(payload) {
Ok(Value::Object(claims_map)) => {
claims_map.into_iter().for_each(|(k, v)| {
jwt_claims.insert(k, v);
});
}
Ok(value) => { warning!("Not valid payload map: {}", value); }
Err(e) => { warning!("Not valid payload value: {}", e); }
};
}
match (payload, claims) {
(Some(_), _) => {}
(Some(_), None) => {}
(_, Some(claims)) => {
for claim in claims {
// TODO support multiple claim types
match split_claim(claim) {
None => { warning!("Claim '{}' do not contains ':'", claim); }
Some((k, v)) => { jwt_claims.insert(k, Value::String(v)); }
Some((k, v)) => { jwt_claims.insert(k, v); }
}
}
if !jwt_claims.contains_key("sub") {
@@ -123,9 +134,9 @@ fn sign_jwt(slot: &str, pin_opt: &Option<&str>, mut header: Header, payload: &Op
debugging!("Claims: {:?}", claims);
let header = opt_result!(header.to_base64(), "Header to base64 failed: {}");
let claims = match payload {
Some(payload) => Cow::Owned(util::base64_encode_url_safe_no_pad(payload.as_bytes())),
None => opt_result!(claims.to_base64(), "Claims to base64 failed: {}"),
let claims = match (payload, claims.is_empty()) {
(Some(payload), true) => Cow::Owned(util::base64_encode_url_safe_no_pad(payload.as_bytes())),
(_, _) => opt_result!(claims.to_base64(), "Claims to base64 failed: {}"),
};
let mut tobe_signed = vec![];
@@ -148,12 +159,22 @@ fn sign_jwt(slot: &str, pin_opt: &Option<&str>, mut header: Header, payload: &Op
Ok([&*header, &*claims, &signature].join(SEPARATOR))
}
fn split_claim(claim: &str) -> Option<(String, String)> {
fn split_claim(claim: &str) -> Option<(String, Value)> {
let mut k = String::new();
let mut v = String::new();
let mut claim_chars = claim.chars().peekable();
let ty = if let Some('^') = claim_chars.peek() {
let _ = claim_chars.next();
match claim_chars.next() {
None => return None,
Some(t) => Some(t),
}
} else {
None
};
let mut is_k = true;
for c in claim.chars() {
for c in claim_chars {
if is_k {
if c == ':' {
is_k = false;
@@ -165,5 +186,28 @@ fn split_claim(claim: &str) -> Option<(String, String)> {
}
}
iff!(is_k, None, Some((k, v)))
if is_k {
return None;
}
match ty {
None | Some('s') => Some((k, Value::String(v))),
Some('b') => Some((k, Value::Bool(vec!["true", "yes", "1"].contains(&v.as_str())))),
Some('i') | Some('n') => {
if let Ok(i) = v.parse::<i64>() {
return Some((k, Value::Number(Number::from(i))));
}
if let Ok(f) = v.parse::<f64>() {
if let Some(number_f64) = Number::from_f64(f) {
return Some((k, Value::Number(number_f64)));
}
}
warning!("Bad number: {} in claim: {}", v, claim);
None
}
_ => {
warning!("Unknown type: {} in claim: {}", ty.unwrap(), claim);
None
}
}
}