1use base64::{engine::general_purpose, Engine as _};
2use hmac::{Hmac, Mac};
3use sha2::Sha256;
4use subtle::ConstantTimeEq;
5
6#[cfg(feature = "enterprise")]
7pub mod enterprise;
8
9type HmacSha256 = Hmac<Sha256>;
12
13pub fn issue_simple_token(secret: &[u8], session_id: &str, consumer_did: &str, provider_did: &str) -> String {
14 let mut mac = HmacSha256::new_from_slice(secret).expect("HMAC can take key of any size");
15 let msg = format!("{}|{}|{}", session_id, consumer_did, provider_did);
16 mac.update(msg.as_bytes());
17 let result = mac.finalize().into_bytes();
18 general_purpose::URL_SAFE_NO_PAD.encode(result)
19}
20
21pub fn validate_simple_token(token: &str, secret: &[u8], session_id: &str, consumer_did: &str, provider_did: &str) -> bool {
22 let expected = issue_simple_token(secret, session_id, consumer_did, provider_did);
23 expected.as_bytes().ct_eq(token.as_bytes()).into()
25}
26
27#[cfg(test)]
28mod tests {
29 use super::*;
30
31 #[test]
32 fn roundtrip_token() {
33 let secret = b"supersecret";
34 let token = issue_simple_token(secret, "sess-1", "did:mesh:agent:consumer", "did:mesh:agent:provider");
35 assert!(validate_simple_token(&token, secret, "sess-1", "did:mesh:agent:consumer", "did:mesh:agent:provider"));
36 }
37}