this repo has no description
1use super::{Claims, TokenData, UnsafeClaims};
2use anyhow::{Context, Result, anyhow};
3use base64::Engine as _;
4use base64::engine::general_purpose::URL_SAFE_NO_PAD;
5use chrono::Utc;
6use k256::ecdsa::{Signature, SigningKey, VerifyingKey, signature::Verifier};
7
8pub fn get_did_from_token(token: &str) -> Result<String, String> {
9 let parts: Vec<&str> = token.split('.').collect();
10 if parts.len() != 3 {
11 return Err("Invalid token format".to_string());
12 }
13
14 let payload_bytes = URL_SAFE_NO_PAD
15 .decode(parts[1])
16 .map_err(|e| format!("Base64 decode failed: {}", e))?;
17
18 let claims: UnsafeClaims =
19 serde_json::from_slice(&payload_bytes).map_err(|e| format!("JSON decode failed: {}", e))?;
20
21 Ok(claims.sub.unwrap_or(claims.iss))
22}
23
24pub fn verify_token(token: &str, key_bytes: &[u8]) -> Result<TokenData<Claims>> {
25 let parts: Vec<&str> = token.split('.').collect();
26 if parts.len() != 3 {
27 return Err(anyhow!("Invalid token format"));
28 }
29
30 let header_b64 = parts[0];
31 let claims_b64 = parts[1];
32 let signature_b64 = parts[2];
33
34 let signature_bytes = URL_SAFE_NO_PAD
35 .decode(signature_b64)
36 .context("Base64 decode of signature failed")?;
37 let signature = Signature::from_slice(&signature_bytes)
38 .map_err(|e| anyhow!("Invalid signature format: {}", e))?;
39
40 let signing_key = SigningKey::from_slice(key_bytes)?;
41 let verifying_key = VerifyingKey::from(&signing_key);
42
43 let message = format!("{}.{}", header_b64, claims_b64);
44 verifying_key
45 .verify(message.as_bytes(), &signature)
46 .map_err(|e| anyhow!("Signature verification failed: {}", e))?;
47
48 let claims_bytes = URL_SAFE_NO_PAD
49 .decode(claims_b64)
50 .context("Base64 decode of claims failed")?;
51 let claims: Claims =
52 serde_json::from_slice(&claims_bytes).context("JSON decode of claims failed")?;
53
54 let now = Utc::now().timestamp() as usize;
55 if claims.exp < now {
56 return Err(anyhow!("Token expired"));
57 }
58
59 Ok(TokenData { claims })
60}