- 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
40 lines
1.2 KiB
Rust
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")
|
|
}
|