Skip to main content

webgates_codecs/
lib.rs

1#![deny(missing_docs)]
2#![deny(unsafe_code)]
3#![deny(clippy::unwrap_used)]
4#![deny(clippy::expect_used)]
5/*!
6# webgates-codecs
7
8JWT encoding, decoding, validation, and JWKS helpers for `webgates` applications.
9
10This crate is the codec layer of the workspace. It gives you the building blocks
11for encoding, decoding, and validating JWT payloads without pulling in HTTP,
12cookies, middleware, or framework-specific integration.
13
14## When to use this crate
15
16Use `webgates-codecs` when you want:
17
18- a small codec abstraction via [`Codec`]
19- JWT claim types and a JWT codec in [`jwt`]
20- issuer-aware token validation helpers
21- ES384 JWKS key modeling in [`jwt::jwks`]
22- structured codec and JWT error types
23
24The crate depends only on shared core types from `webgates-core` and keeps
25transport concerns out of scope.
26
27## Quick start
28
29```rust
30use std::sync::Arc;
31use webgates_codecs::jsonwebtoken::crypto::rust_crypto::DEFAULT_PROVIDER as JWT_CRYPTO_PROVIDER;
32use webgates_codecs::jwt::{JsonWebToken, JwtClaims, RegisteredClaims};
33use webgates_codecs::jwt::validation_service::JwtValidationService;
34use webgates_codecs::Codec;
35use webgates_core::accounts::Account;
36use webgates_core::groups::Group;
37use webgates_core::roles::Role;
38
39type Claims = JwtClaims<Account<Role, Group>>;
40
41let _ = JWT_CRYPTO_PROVIDER.install_default();
42let codec = Arc::new(JsonWebToken::<Claims>::default());
43let claims = JwtClaims::new(
44    Account::<Role, Group>::new("user@example.com"),
45    RegisteredClaims::new("my-app", 4_102_444_800),
46);
47
48let token = codec.encode(&claims)?;
49let decoded = codec.decode(&token)?;
50assert!(decoded.has_issuer("my-app"));
51
52let validator = JwtValidationService::new(Arc::clone(&codec), "my-app");
53let _ = validator.validate_token(std::str::from_utf8(&token)?);
54# Ok::<(), Box<dyn std::error::Error>>(())
55```
56
57## Getting started on docs.rs
58
59A good reading order is:
60
611. [`Codec`]
622. [`jwt::RegisteredClaims`]
633. [`jwt::JwtClaims`]
644. [`jwt::JsonWebToken`]
655. [`jwt::validation_service::JwtValidationService`]
666. [`jwt::jwks`]
67*/
68
69use serde::{Serialize, de::DeserializeOwned};
70
71pub mod errors;
72pub mod jwt;
73
74pub use jsonwebtoken;
75
76use errors::{CodecsError, JwtError};
77
78/// Result alias used by codec implementations in this crate.
79pub type Result<T> = std::result::Result<T, Error>;
80
81/// Root error type for `webgates-codecs`.
82#[derive(Debug, thiserror::Error)]
83pub enum Error {
84    /// Codec/serialization category errors.
85    #[error(transparent)]
86    Codecs(#[from] CodecsError),
87
88    /// JWT processing category errors.
89    #[error(transparent)]
90    Jwt(#[from] JwtError),
91}
92
93/// Encodes and decodes typed payloads.
94///
95/// Higher-level crates build on this small abstraction. A codec takes a typed
96/// payload, produces an opaque encoded representation, and can later decode
97/// that representation back into the typed payload.
98pub trait Codec
99where
100    Self: Clone,
101    Self::Payload: Serialize + DeserializeOwned,
102{
103    /// Type of the payload being encoded/decoded.
104    type Payload;
105
106    /// Encodes a payload into an opaque, implementation-defined byte vector.
107    ///
108    /// Returns an error if serialization, signing, encryption, or other
109    /// encoding steps fail.
110    fn encode(&self, payload: &Self::Payload) -> Result<Vec<u8>>;
111
112    /// Decodes a previously encoded payload.
113    ///
114    /// Returns an error if the value is malformed, tampered with, or otherwise
115    /// fails integrity or authenticity validation.
116    fn decode(&self, encoded_value: &[u8]) -> Result<Self::Payload>;
117}