Skip to content

Commit a0431d8

Browse files
committed
feat: Remove builder style implementation
1 parent 337f9ed commit a0431d8

File tree

3 files changed

+82
-264
lines changed

3 files changed

+82
-264
lines changed

src/decoding.rs

Lines changed: 50 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -232,17 +232,34 @@ pub fn decode<T: DeserializeOwned>(
232232
return Err(new_error(ErrorKind::InvalidAlgorithm));
233233
}
234234

235-
let decoder = decoder_factory(&header.alg, key)?.with_validation(validation)?;
235+
let verifying_provider = jwt_verifier_factory(&header.alg, key)?;
236236

237-
decoder.decode(token)
237+
_decode(token, validation, verifying_provider)
238238
}
239239

240-
/// Return the correct decoder based on the `algorithm`.
241-
fn decoder_factory(algorithm: &Algorithm, key: &DecodingKey) -> Result<JwtDecoder> {
240+
/// # Todo
241+
///
242+
/// - Documentation
243+
pub fn _decode<T: DeserializeOwned>(
244+
token: &str,
245+
validation: &Validation,
246+
verifying_provider: Box<dyn JwtVerifier>,
247+
) -> Result<TokenData<T>> {
248+
let (header, claims) = verify_signature(token, validation, verifying_provider)?;
249+
250+
let decoded_claims = DecodedJwtPartClaims::from_jwt_part_claims(claims)?;
251+
let claims = decoded_claims.deserialize()?;
252+
validate(decoded_claims.deserialize()?, validation)?;
253+
254+
Ok(TokenData { header, claims })
255+
}
256+
257+
/// Return the correct [`JwtVerifier`] based on the `algorithm`.
258+
fn jwt_verifier_factory(algorithm: &Algorithm, key: &DecodingKey) -> Result<Box<dyn JwtVerifier>> {
242259
let jwt_encoder = match algorithm {
243-
Algorithm::HS256 => JwtDecoder::hs_256(key.try_into()?)?,
244-
Algorithm::HS384 => JwtDecoder::hs_384(key.try_into()?)?,
245-
Algorithm::HS512 => JwtDecoder::hs_512(key.try_into()?)?,
260+
Algorithm::HS256 => Box::new(Hs256::new(key.try_into()?)?) as Box<dyn JwtVerifier>,
261+
Algorithm::HS384 => Box::new(Hs384::new(key.try_into()?)?) as Box<dyn JwtVerifier>,
262+
Algorithm::HS512 => Box::new(Hs512::new(key.try_into()?)?) as Box<dyn JwtVerifier>,
246263
Algorithm::ES256 => todo!(),
247264
Algorithm::ES384 => todo!(),
248265
Algorithm::RS256 => todo!(),
@@ -287,139 +304,40 @@ pub fn decode_header(token: &str) -> Result<Header> {
287304
Header::from_encoded(header)
288305
}
289306

290-
/// A builder style JWT decoder
291-
///
292-
/// # Examples
293-
///
294-
/// ```
295-
/// use jsonwebtoken::{JwtDecoder, HmacSecret};
296-
/// use serde::{Serialize, Deserialize};
307+
/// Verify signature of a JWT, and return header object and raw payload
297308
///
298-
/// #[derive(Debug, Serialize, Deserialize)]
299-
/// struct Claims {
300-
/// sub: String,
301-
/// company: String,
302-
/// exp: usize,
303-
/// }
304-
///
305-
/// let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.9r56oF7ZliOBlOAyiOFperTGxBtPykRQiWNFxhDCW98";
306-
///
307-
/// let hmac_secret = HmacSecret::from_secret(b"secret");
308-
///
309-
/// let claims = JwtDecoder::hs_256(hmac_secret)
310-
/// .unwrap()
311-
/// .decode::<Claims>(&token)
312-
/// .unwrap();
313-
/// ```
314-
pub struct JwtDecoder {
309+
/// If the token or its signature is invalid, it will return an error.
310+
fn verify_signature<'a>(
311+
token: &'a str,
312+
validation: &Validation,
315313
verifying_provider: Box<dyn JwtVerifier>,
316-
validation: Validation,
317-
}
318-
319-
impl JwtDecoder {
320-
/// Create a new [`JwtDecoder`] with any `verifying_provider` that implements the [`JwtVerifier`] trait.
321-
pub fn from_verifier<V: JwtVerifier + 'static>(verifying_provider: V) -> Self {
322-
Self::from_boxed_verifiyer(Box::new(verifying_provider))
314+
) -> Result<(Header, &'a str)> {
315+
if validation.validate_signature && validation.algorithms.is_empty() {
316+
return Err(new_error(ErrorKind::MissingAlgorithm));
323317
}
324318

325-
/// Create a new [`JwtDecoder`] with any `verifying_provider` implements the [`JwtVerifier`] trait.
326-
pub fn from_boxed_verifiyer(verifying_provider: Box<dyn JwtVerifier>) -> Self {
327-
let validation = Validation::new(verifying_provider.algorithm());
319+
// Todo: This behaviour is currently not captured anywhere.
320+
// if validation.validate_signature {
321+
// for alg in &validation.algorithms {
322+
// if key.family != alg.family() {
323+
// return Err(new_error(ErrorKind::InvalidAlgorithm));
324+
// }
325+
// }
326+
// }
328327

329-
Self { verifying_provider, validation }
330-
}
331-
332-
/// Provide custom a custom validation configuration.
333-
///
334-
/// # Examples
335-
///
336-
/// ```
337-
/// use jsonwebtoken::{JwtDecoder, HmacSecret, Validation, Algorithm};
338-
///
339-
/// let hmac_secret = HmacSecret::from_secret(b"secret");
340-
/// let mut validation = Validation::new(Algorithm::HS256);
341-
/// validation.leeway = 5;
342-
///
343-
/// let jwt_decoder = JwtDecoder::hs_256(hmac_secret)
344-
/// .unwrap()
345-
/// .with_validation(&validation)
346-
/// .unwrap();
347-
/// ```
348-
pub fn with_validation(mut self, validation: &Validation) -> Result<Self> {
349-
// Check that the validation contains the correct algorithm
350-
if validation.validate_signature
351-
&& !validation.algorithms.contains(&self.verifying_provider.algorithm())
352-
{
353-
return Err(new_error(crate::errors::ErrorKind::InvalidAlgorithm));
354-
}
355-
356-
self.validation = validation.clone();
357-
Ok(self)
358-
}
359-
360-
/// Decode and verify a JWT `token` using the `verifying_provider` and `validation` of the [`JwtDecoder`]
361-
pub fn decode<T: DeserializeOwned>(&self, token: &str) -> Result<TokenData<T>> {
362-
let (header, claims) = self.verify_signature(token)?;
363-
364-
let decoded_claims = DecodedJwtPartClaims::from_jwt_part_claims(claims)?;
365-
let claims = decoded_claims.deserialize()?;
366-
validate(decoded_claims.deserialize()?, &self.validation)?;
367-
368-
Ok(TokenData { header, claims })
369-
}
370-
371-
/// Verify signature of a JWT, and return header object and raw payload
372-
///
373-
/// If the token or its signature is invalid, it will return an error.
374-
fn verify_signature<'a>(&self, token: &'a str) -> Result<(Header, &'a str)> {
375-
if self.validation.validate_signature && self.validation.algorithms.is_empty() {
376-
return Err(new_error(ErrorKind::MissingAlgorithm));
377-
}
328+
let (signature, message) = expect_two!(token.rsplitn(2, '.'));
329+
let (payload, header) = expect_two!(message.rsplitn(2, '.'));
330+
let header = Header::from_encoded(header)?;
378331

379-
// Todo: This behaviour is currently not captured anywhere.
380-
// if validation.validate_signature {
381-
// for alg in &validation.algorithms {
382-
// if key.family != alg.family() {
383-
// return Err(new_error(ErrorKind::InvalidAlgorithm));
384-
// }
385-
// }
386-
// }
387-
388-
let (signature, message) = expect_two!(token.rsplitn(2, '.'));
389-
let (payload, header) = expect_two!(message.rsplitn(2, '.'));
390-
let header = Header::from_encoded(header)?;
391-
392-
if self.validation.validate_signature && !self.validation.algorithms.contains(&header.alg) {
393-
return Err(new_error(ErrorKind::InvalidAlgorithm));
394-
}
395-
396-
if self.validation.validate_signature
397-
&& self.verifying_provider.verify(message.as_bytes(), &b64_decode(signature)?).is_err()
398-
{
399-
return Err(new_error(ErrorKind::InvalidSignature));
400-
}
401-
402-
Ok((header, payload))
403-
}
404-
405-
/// Create new [`JwtDecoder`] with the `HS256` algorithm.
406-
pub fn hs_256(secret: HmacSecret) -> Result<JwtDecoder> {
407-
let verifying_provider = Box::new(Hs256::new(secret)?);
408-
409-
Ok(JwtDecoder::from_boxed_verifiyer(verifying_provider))
332+
if validation.validate_signature && !validation.algorithms.contains(&header.alg) {
333+
return Err(new_error(ErrorKind::InvalidAlgorithm));
410334
}
411335

412-
/// Create new [`JwtDecoder`] with the `HS384` algorithm.
413-
pub fn hs_384(secret: HmacSecret) -> Result<JwtDecoder> {
414-
let verifying_provider = Box::new(Hs384::new(secret)?);
415-
416-
Ok(JwtDecoder::from_boxed_verifiyer(verifying_provider))
336+
if validation.validate_signature
337+
&& verifying_provider.verify(message.as_bytes(), &b64_decode(signature)?).is_err()
338+
{
339+
return Err(new_error(ErrorKind::InvalidSignature));
417340
}
418341

419-
/// Create new [`JwtDecoder`] with the `HS512` algorithm.
420-
pub fn hs_512(secret: HmacSecret) -> Result<JwtDecoder> {
421-
let verifying_provider = Box::new(Hs512::new(secret)?);
422-
423-
Ok(JwtDecoder::from_boxed_verifiyer(verifying_provider))
424-
}
342+
Ok((header, payload))
425343
}

src/encoding.rs

Lines changed: 30 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -131,17 +131,38 @@ pub fn encode<T: Serialize>(header: &Header, claims: &T, key: &EncodingKey) -> R
131131
return Err(new_error(ErrorKind::InvalidAlgorithm));
132132
}
133133

134-
let jwt_encoder = encoder_factory(&header.alg, key)?.with_header(header)?;
134+
let signing_provider = jwt_signer_factory(&header.alg, key)?;
135135

136-
jwt_encoder.encode(claims)
136+
_encode(header, claims, signing_provider)
137137
}
138138

139-
/// Return the correct [`JwtEncoder`] based on the `algorithm`.
140-
fn encoder_factory(algorithm: &Algorithm, key: &EncodingKey) -> Result<JwtEncoder> {
141-
let jwt_encoder = match algorithm {
142-
Algorithm::HS256 => JwtEncoder::hs_256(key.into())?,
143-
Algorithm::HS384 => JwtEncoder::hs_384(key.into())?,
144-
Algorithm::HS512 => JwtEncoder::hs_512(key.into())?,
139+
/// # Todo
140+
///
141+
/// - Documentation
142+
pub fn _encode<T: Serialize>(
143+
header: &Header,
144+
claims: &T,
145+
signing_provider: Box<dyn JwtSigner>,
146+
) -> Result<String> {
147+
if signing_provider.algorithm() != header.alg {
148+
return Err(new_error(ErrorKind::InvalidAlgorithm));
149+
}
150+
151+
let encoded_header = b64_encode_part(&header)?;
152+
let encoded_claims = b64_encode_part(claims)?;
153+
let message = [encoded_header, encoded_claims].join(".");
154+
155+
let signature = b64_encode(&signing_provider.sign(message.as_bytes()));
156+
157+
Ok([message, signature].join("."))
158+
}
159+
160+
/// Return the correct [`JwtSigner`] based on the `algorithm`.
161+
fn jwt_signer_factory(algorithm: &Algorithm, key: &EncodingKey) -> Result<Box<dyn JwtSigner>> {
162+
let jwt_signer = match algorithm {
163+
Algorithm::HS256 => Box::new(Hs256::new(key.into())?) as Box<dyn JwtSigner>,
164+
Algorithm::HS384 => Box::new(Hs384::new(key.into())?) as Box<dyn JwtSigner>,
165+
Algorithm::HS512 => Box::new(Hs512::new(key.into())?) as Box<dyn JwtSigner>,
145166
Algorithm::ES256 => todo!(),
146167
Algorithm::ES384 => todo!(),
147168
Algorithm::RS256 => todo!(),
@@ -153,7 +174,7 @@ fn encoder_factory(algorithm: &Algorithm, key: &EncodingKey) -> Result<JwtEncode
153174
Algorithm::EdDSA => todo!(),
154175
};
155176

156-
Ok(jwt_encoder)
177+
Ok(jwt_signer)
157178
}
158179

159180
/// Convert an [`&EncodingKey`] to an [`HmacSecret`].
@@ -162,124 +183,3 @@ impl From<&EncodingKey> for HmacSecret {
162183
HmacSecret::from_secret(&key.content)
163184
}
164185
}
165-
166-
/// A builder style JWT encoder.
167-
///
168-
/// # Examples
169-
///
170-
/// ```
171-
/// use serde::{Deserialize, Serialize};
172-
/// use jsonwebtoken::{JwtEncoder, HmacSecret};
173-
///
174-
/// #[derive(Debug, Serialize, Deserialize)]
175-
/// struct Claims {
176-
/// sub: String,
177-
/// company: String
178-
/// }
179-
///
180-
/// let my_claims = Claims {
181-
/// sub: "[email protected]".to_owned(),
182-
/// company: "ACME".to_owned()
183-
/// };
184-
///
185-
/// let hmac_secret = HmacSecret::from_secret(b"secret");
186-
///
187-
/// let token = JwtEncoder::hs_256(hmac_secret)
188-
/// .unwrap()
189-
/// .encode(&my_claims)
190-
/// .unwrap();
191-
/// ```
192-
pub struct JwtEncoder {
193-
signing_provider: Box<dyn JwtSigner>,
194-
header: Header,
195-
}
196-
197-
impl JwtEncoder {
198-
/// Create a new [`JwtEncoder`] with any `signing_provider` that implements the [`JwtSigner`] trait.
199-
pub fn from_signer<S: JwtSigner + 'static>(signing_provider: S) -> Self {
200-
Self::from_boxed_signer(Box::new(signing_provider))
201-
}
202-
203-
/// Create a new [`JwtEncoder`] with any `signing_provider` that implements the [`JwtSigner`] trait.
204-
pub fn from_boxed_signer(signing_provider: Box<dyn JwtSigner>) -> Self {
205-
// Determine a default header
206-
let mut header = Header::new(signing_provider.algorithm());
207-
header.typ = Some("JWT".to_owned());
208-
209-
Self { signing_provider, header }
210-
}
211-
212-
/// Provide a custom header.
213-
///
214-
/// This would be used in the rare cases that fields other than `algorithm` and `type` need to be populated.
215-
///
216-
/// # Examples
217-
///
218-
/// ```
219-
/// use serde::{Deserialize, Serialize};
220-
/// use jsonwebtoken::{JwtEncoder, HmacSecret, Header, Algorithm};
221-
///
222-
/// #[derive(Debug, Serialize, Deserialize)]
223-
/// struct Claims {
224-
/// sub: String,
225-
/// company: String
226-
/// }
227-
///
228-
/// let my_claims = Claims {
229-
/// sub: "[email protected]".to_owned(),
230-
/// company: "ACME".to_owned()
231-
/// };
232-
///
233-
/// let hmac_secret = HmacSecret::from_secret(b"secret");
234-
/// let mut header = Header::new(Algorithm::HS256);
235-
/// header.cty = Some("content-type".to_owned());
236-
///
237-
/// let token = JwtEncoder::hs_256(hmac_secret)
238-
/// .unwrap()
239-
/// .with_header(&header)
240-
/// .unwrap()
241-
/// .encode(&my_claims)
242-
/// .unwrap();
243-
/// ```
244-
pub fn with_header(mut self, header: &Header) -> Result<Self> {
245-
// Check that the header makes use of the correct algorithm
246-
if header.alg != self.signing_provider.algorithm() {
247-
return Err(new_error(crate::errors::ErrorKind::InvalidAlgorithm));
248-
}
249-
250-
self.header = header.clone();
251-
Ok(self)
252-
}
253-
254-
/// Encode and sign the `claims` as a JWT using the `signing_provider` of the [`JwtEncoder`].
255-
pub fn encode<T: Serialize>(&self, claims: &T) -> Result<String> {
256-
let encoded_header = b64_encode_part(&self.header)?;
257-
let encoded_claims = b64_encode_part(claims)?;
258-
let message = [encoded_header, encoded_claims].join(".");
259-
260-
let signature = b64_encode(&self.signing_provider.sign(message.as_bytes()));
261-
262-
Ok([message, signature].join("."))
263-
}
264-
265-
/// Create new [`JwtEncoder`] with the `HS256` algorithm.
266-
pub fn hs_256(secret: HmacSecret) -> Result<JwtEncoder> {
267-
let signing_provider = Box::new(Hs256::new(secret)?);
268-
269-
Ok(JwtEncoder::from_boxed_signer(signing_provider))
270-
}
271-
272-
/// Create new [`JwtEncoder`] with the `HS384` algorithm.
273-
pub fn hs_384(secret: HmacSecret) -> Result<JwtEncoder> {
274-
let signing_provider = Box::new(Hs384::new(secret)?);
275-
276-
Ok(JwtEncoder::from_boxed_signer(signing_provider))
277-
}
278-
279-
/// Create new [`JwtEncoder`] with the `HS512` algorithm.
280-
pub fn hs_512(secret: HmacSecret) -> Result<JwtEncoder> {
281-
let signing_provider = Box::new(Hs512::new(secret)?);
282-
283-
Ok(JwtEncoder::from_boxed_signer(signing_provider))
284-
}
285-
}

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ compile_error!(
1010

1111
pub use algorithms::Algorithm;
1212
pub use crypto::hmac::HmacSecret;
13-
pub use decoding::{decode, decode_header, DecodingKey, JwtDecoder, TokenData};
14-
pub use encoding::{encode, EncodingKey, JwtEncoder};
13+
pub use decoding::{decode, decode_header, DecodingKey, TokenData, _decode};
14+
pub use encoding::{encode, EncodingKey, _encode};
1515
pub use header::Header;
1616
pub use validation::{get_current_timestamp, Validation};
1717

0 commit comments

Comments
 (0)