1use std::marker::PhantomData;
3
4use crate::crypto::sign;
5use crate::errors::{ErrorKind, Result, new_error};
6use crate::serialization::{DecodedJwtPartClaims, b64_encode_part};
7use crate::validation::validate;
8use crate::{DecodingKey, EncodingKey, Header, TokenData, Validation};
9
10use crate::decoding::{jwt_verifier_factory, verify_signature_body};
11use serde::de::DeserializeOwned;
12use serde::{Deserialize, Serialize};
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct Jws<C> {
17 pub protected: String,
21 pub payload: String,
25 pub signature: String,
29 #[serde(skip)]
31 pub _pd: PhantomData<C>,
32}
33
34pub fn encode<T: Serialize>(
38 header: &Header,
39 claims: Option<&T>,
40 key: &EncodingKey,
41) -> Result<Jws<T>> {
42 if key.family != header.alg.family() {
43 return Err(new_error(ErrorKind::InvalidAlgorithm));
44 }
45 let encoded_header = b64_encode_part(header)?;
46 let encoded_claims = match claims {
47 Some(claims) => b64_encode_part(claims)?,
48 None => "".to_string(),
49 };
50 let message = [encoded_header.as_str(), encoded_claims.as_str()].join(".");
51 let signature = sign(message.as_bytes(), key, header.alg)?;
52
53 Ok(Jws {
54 protected: encoded_header,
55 payload: encoded_claims,
56 signature,
57 _pd: Default::default(),
58 })
59}
60
61pub fn decode<T: DeserializeOwned>(
63 jws: &Jws<T>,
64 key: &DecodingKey,
65 validation: &Validation,
66) -> Result<TokenData<T>> {
67 let header = Header::from_encoded(&jws.protected)?;
68 let message = [jws.protected.as_str(), jws.payload.as_str()].join(".");
69
70 let verifying_provider = jwt_verifier_factory(&header.alg, key)?;
71 verify_signature_body(
72 message.as_bytes(),
73 jws.signature.as_bytes(),
74 &header,
75 validation,
76 verifying_provider,
77 )?;
78
79 let decoded_claims = DecodedJwtPartClaims::from_jwt_part_claims(&jws.payload)?;
80 let claims = decoded_claims.deserialize()?;
81 validate(decoded_claims.deserialize()?, validation)?;
82
83 Ok(TokenData { header, claims })
84}