Files
harmony/nats/jwt/src/xkey.rs
Jean-Gabriel Gill-Couture 65daa76658 feat: NATS auth callout e2e integration test
- nats-jwt crate: JWT builder types for user claims, authorization
  request/response, account claims, algorithm encode/decode
- harmony-nats-callout crate: Zitadel OIDC JWT validator, callout
  service scaffold, account manager (WIP)
- integration-test-callout: end-to-end test validating the full
  auth callout flow — device connects with Zitadel JWT → callout
  validates JWT → returns per-device user JWT with scoped
  permissions → device can pub/sub on its own subjects only
- Mock OIDC server for test (JWKS + openid-configuration)
- Negative test: device A cannot subscribe to device B's subjects
- Added UserClaimsBuilder::audience() for account-scoped user JWTs
2026-04-28 23:15:18 -04:00

40 lines
1.2 KiB
Rust

use nkeys::XKey;
use crate::error::Error;
pub fn xkey_seal(
payload: &[u8],
sender_seed: &str,
recipient_pubkey: &str,
) -> Result<Vec<u8>, Error> {
let sender = XKey::from_seed(sender_seed)
.map_err(|e| Error::XKey(format!("invalid sender xkey seed: {e}")))?;
let recipient = XKey::from_public_key(recipient_pubkey)
.map_err(|e| Error::XKey(format!("invalid recipient pubkey: {e}")))?;
sender
.seal(payload, &recipient)
.map_err(|e| Error::XKey(format!("seal failed: {e}")))
}
pub fn xkey_open(
payload: &[u8],
recipient_seed: &str,
sender_pubkey: &str,
) -> Result<Vec<u8>, Error> {
let recipient = XKey::from_seed(recipient_seed)
.map_err(|e| Error::XKey(format!("invalid recipient xkey seed: {e}")))?;
let sender = XKey::from_public_key(sender_pubkey)
.map_err(|e| Error::XKey(format!("invalid sender pubkey: {e}")))?;
recipient
.open(payload, &sender)
.map_err(|e| Error::XKey(format!("open failed: {e}")))
}
pub fn is_encrypted(payload: &[u8]) -> bool {
if payload.len() < 4 {
return true;
}
let prefix = String::from_utf8_lossy(&payload[..4]);
!prefix.starts_with("eyJ0")
}