1use crate::{CommonError, Result, SmartString};
4use jsonwebtoken::{Algorithm, EncodingKey, Header};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Serialize, Deserialize)]
9pub struct JwtClaims {
10 pub access_key: SmartString,
12 pub nonce: SmartString,
14 #[serde(skip_serializing_if = "Option::is_none")]
16 pub query_hash: Option<SmartString>,
17 #[serde(skip_serializing_if = "Option::is_none")]
19 pub body_hash: Option<SmartString>,
20 #[serde(skip_serializing_if = "Option::is_none")]
22 pub exp: Option<i64>,
23}
24
25impl JwtClaims {
26 #[must_use]
28 pub fn new(access_key: SmartString) -> Self {
29 Self {
30 access_key,
31 nonce: uuid::Uuid::new_v4().to_string().into(),
32 query_hash: None,
33 body_hash: None,
34 exp: None,
35 }
36 }
37
38 #[must_use]
40 pub fn with_query_hash(mut self, query_hash: SmartString) -> Self {
41 self.query_hash = Some(query_hash);
42 self
43 }
44
45 #[must_use]
47 pub fn with_body_hash(mut self, body_hash: SmartString) -> Self {
48 self.body_hash = Some(body_hash);
49 self
50 }
51}
52
53pub fn generate_jwt_hs256(claims: &JwtClaims, secret: &str) -> Result<SmartString> {
55 let header = Header::new(Algorithm::HS256);
56 let encoding_key = EncodingKey::from_secret(secret.as_ref());
57
58 jsonwebtoken::encode(&header, claims, &encoding_key)
59 .map(|s| s.into())
60 .map_err(|e| CommonError::Auth(format!("JWT encoding error: {e}").into()))
61}