jwt_service/
impl.rs

1use super::*;
2
3impl JwtConfig {
4    /// Creates a new JwtConfig instance.
5    ///
6    /// # Arguments
7    ///
8    /// - `secret` - The secret key for signing tokens.
9    /// - `expiration_seconds` - Token validity duration in seconds.
10    /// - `AsRef<str>` - The issuer identifier for the token.
11    ///
12    /// # Returns
13    ///
14    /// - `JwtConfig` - The configured JwtConfig instance.
15    pub fn new<S>(secret: S, expiration_seconds: u64, issuer: S) -> Self
16    where
17        S: AsRef<str>,
18    {
19        Self {
20            secret: secret.as_ref().to_string(),
21            expiration_seconds,
22            issuer: issuer.as_ref().to_string(),
23        }
24    }
25
26    /// Returns a reference to the secret key.
27    ///
28    /// # Returns
29    ///
30    /// - `&String` - The secret key.
31    pub fn get_secret(&self) -> &String {
32        &self.secret
33    }
34
35    /// Sets the secret key.
36    ///
37    /// # Arguments
38    ///
39    /// - `AsRef<str>` - The secret key to set.
40    ///
41    /// # Returns
42    ///
43    /// - `&mut Self` - The modified instance for chaining.
44    pub fn set_secret<S>(&mut self, secret: S) -> &mut Self
45    where
46        S: AsRef<str>,
47    {
48        self.secret = secret.as_ref().to_string();
49        self
50    }
51
52    /// Returns the expiration time in seconds.
53    ///
54    /// # Returns
55    ///
56    /// - `u64` - The expiration time.
57    pub fn get_expiration_seconds(&self) -> u64 {
58        self.expiration_seconds
59    }
60
61    /// Sets the expiration time in seconds.
62    ///
63    /// # Arguments
64    ///
65    /// - `u64` - The expiration time to set.
66    ///
67    /// # Returns
68    ///
69    /// - `&mut Self` - The modified instance for chaining.
70    pub fn set_expiration_seconds(&mut self, expiration_seconds: u64) -> &mut Self {
71        self.expiration_seconds = expiration_seconds;
72        self
73    }
74
75    /// Returns a reference to the issuer.
76    ///
77    /// # Returns
78    ///
79    /// - `&String` - The issuer.
80    pub fn get_issuer(&self) -> &String {
81        &self.issuer
82    }
83
84    /// Sets the issuer.
85    ///
86    /// # Arguments
87    ///
88    /// - `AsRef<str>` - The issuer to set.
89    ///
90    /// # Returns
91    ///
92    /// - `&mut Self` - The modified instance for chaining.
93    pub fn set_issuer<S>(&mut self, issuer: S) -> &mut Self
94    where
95        S: AsRef<str>,
96    {
97        self.issuer = issuer.as_ref().to_string();
98        self
99    }
100}
101
102impl JwtExtraJwtClaims {
103    /// Creates a new JwtExtraJwtClaims instance.
104    ///
105    /// # Arguments
106    ///
107    /// - `AsRef<str>` - The subject (user identifier).
108    /// - `AsRef<str>` - The issuer.
109    /// - `usize` - Expiration time as a Unix timestamp.
110    /// - `usize` - Issued at time as a Unix timestamp.
111    /// - `usize` - Not before time as a Unix timestamp.
112    ///
113    /// # Returns
114    ///
115    /// - `JwtExtraJwtClaims` - The created claims instance.
116    pub fn new<S>(sub: S, iss: S, exp: usize, iat: usize, nbf: usize) -> Self
117    where
118        S: AsRef<str>,
119    {
120        Self {
121            sub: sub.as_ref().to_string(),
122            iss: iss.as_ref().to_string(),
123            exp,
124            iat,
125            nbf,
126        }
127    }
128
129    /// Returns a reference to the subject.
130    ///
131    /// # Returns
132    ///
133    /// - `&String` - The subject.
134    pub fn get_sub(&self) -> &String {
135        &self.sub
136    }
137
138    /// Sets the subject.
139    ///
140    /// # Arguments
141    ///
142    /// - `AsRef<str>` - The subject to set.
143    ///
144    /// # Returns
145    ///
146    /// - `&mut Self` - The modified instance for chaining.
147    pub fn set_sub<S>(&mut self, sub: S) -> &mut Self
148    where
149        S: AsRef<str>,
150    {
151        self.sub = sub.as_ref().to_string();
152        self
153    }
154
155    /// Returns a reference to the issuer.
156    ///
157    /// # Returns
158    ///
159    /// - `&String` - The issuer.
160    pub fn get_iss(&self) -> &String {
161        &self.iss
162    }
163
164    /// Sets the issuer.
165    ///
166    /// # Arguments
167    ///
168    /// - `AsRef<str>` - The issuer to set.
169    ///
170    /// # Returns
171    ///
172    /// - `&mut Self` - The modified instance for chaining.
173    pub fn set_iss<S>(&mut self, iss: S) -> &mut Self
174    where
175        S: AsRef<str>,
176    {
177        self.iss = iss.as_ref().to_string();
178        self
179    }
180
181    /// Returns the expiration time.
182    ///
183    /// # Returns
184    ///
185    /// - `usize` - The expiration timestamp.
186    pub fn get_exp(&self) -> usize {
187        self.exp
188    }
189
190    /// Sets the expiration time.
191    ///
192    /// # Arguments
193    ///
194    /// - `exp` - The expiration timestamp to set.
195    ///
196    /// # Returns
197    ///
198    /// - `&mut Self` - The modified instance for chaining.
199    pub fn set_exp(&mut self, exp: usize) -> &mut Self {
200        self.exp = exp;
201        self
202    }
203
204    /// Returns the issued at time.
205    ///
206    /// # Returns
207    ///
208    /// - `usize` - The issued at timestamp.
209    pub fn get_iat(&self) -> usize {
210        self.iat
211    }
212
213    /// Sets the issued at time.
214    ///
215    /// # Arguments
216    ///
217    /// - `usize` - The issued at timestamp to set.
218    ///
219    /// # Returns
220    ///
221    /// - `&mut Self` - The modified instance for chaining.
222    pub fn set_iat(&mut self, iat: usize) -> &mut Self {
223        self.iat = iat;
224        self
225    }
226
227    /// Returns the not before time.
228    ///
229    /// # Returns
230    ///
231    /// - `usize` - The not before timestamp.
232    pub fn get_nbf(&self) -> usize {
233        self.nbf
234    }
235
236    /// Sets the not before time.
237    ///
238    /// # Arguments
239    ///
240    /// - `usize` - The not before timestamp to set.
241    ///
242    /// # Returns
243    ///
244    /// - `&mut Self` - The modified instance for chaining.
245    pub fn set_nbf(&mut self, nbf: usize) -> &mut Self {
246        self.nbf = nbf;
247        self
248    }
249}
250
251impl JwtToken {
252    /// Returns a reference to the token.
253    ///
254    /// # Returns
255    ///
256    /// - `&String` - The token.
257    pub fn get_token(&self) -> &String {
258        &self.token
259    }
260
261    /// Sets the token.
262    ///
263    /// # Arguments
264    ///
265    /// - `AsRef<str>` - The token to set.
266    ///
267    /// # Returns
268    ///
269    /// - `&mut Self` - The modified instance for chaining.
270    pub fn set_token<S>(&mut self, token: S) -> &mut Self
271    where
272        S: AsRef<str>,
273    {
274        self.token = token.as_ref().to_string();
275        self
276    }
277
278    /// Returns a reference to the token type.
279    ///
280    /// # Returns
281    ///
282    /// - `&String` - The token type.
283    pub fn get_token_type(&self) -> &String {
284        &self.token_type
285    }
286
287    /// Sets the token type.
288    ///
289    /// # Arguments
290    ///
291    /// - `token_type` - The token type to set.
292    ///
293    /// # Returns
294    ///
295    /// - `&mut Self` - The modified instance for chaining.
296    pub fn set_token_type<S>(&mut self, token_type: S) -> &mut Self
297    where
298        S: AsRef<str>,
299    {
300        self.token_type = token_type.as_ref().to_string();
301        self
302    }
303
304    /// Returns the expires in value.
305    ///
306    /// # Returns
307    ///
308    /// - `u64` - The expires in value.
309    pub fn get_expires_in(&self) -> u64 {
310        self.expires_in
311    }
312
313    /// Sets the expires in value.
314    ///
315    /// # Arguments
316    ///
317    /// - `u64` - The expires in value to set.
318    ///
319    /// # Returns
320    ///
321    /// - `&mut Self` - The modified instance for chaining.
322    pub fn set_expires_in(&mut self, expires_in: u64) -> &mut Self {
323        self.expires_in = expires_in;
324        self
325    }
326}
327
328impl JwtService {
329    /// Creates a new JwtService instance.
330    ///
331    /// # Arguments
332    ///
333    /// - `JwtConfig` - The JWT configuration.
334    /// - `EncodingKey` - The encoding key for signing tokens.
335    /// - `DecodingKey` - The decoding key for verifying tokens.
336    /// - `Validation` - The validation settings for token verification.
337    ///
338    /// # Returns
339    ///
340    /// - `JwtService` - The created service instance.
341    pub fn new(
342        config: JwtConfig,
343        encoding_key: EncodingKey,
344        decoding_key: DecodingKey,
345        validation: Validation,
346    ) -> Self {
347        Self {
348            config,
349            encoding_key,
350            decoding_key,
351            validation,
352        }
353    }
354
355    /// Returns a reference to the JWT configuration.
356    ///
357    /// # Returns
358    ///
359    /// - `&JwtConfig` - The configuration.
360    pub fn get_config(&self) -> &JwtConfig {
361        &self.config
362    }
363
364    /// Returns a reference to the encoding key.
365    ///
366    /// # Returns
367    ///
368    /// - `&EncodingKey` - The encoding key.
369    pub fn get_encoding_key(&self) -> &EncodingKey {
370        &self.encoding_key
371    }
372
373    /// Returns a reference to the decoding key.
374    ///
375    /// # Returns
376    ///
377    /// - `&DecodingKey` - The decoding key.
378    pub fn get_decoding_key(&self) -> &DecodingKey {
379        &self.decoding_key
380    }
381
382    /// Returns a reference to the validation settings.
383    ///
384    /// # Returns
385    ///
386    /// - `&Validation` - The validation settings.
387    pub fn get_validation(&self) -> &Validation {
388        &self.validation
389    }
390}
391
392impl<T: Default> CustomExtraJwtClaims<T> {
393    /// Returns a reference to the custom payload data.
394    ///
395    /// # Returns
396    ///
397    /// - `&T` - The custom payload data.
398    pub fn get_custom(&self) -> &T {
399        &self.custom
400    }
401
402    /// Sets the custom payload data.
403    ///
404    /// # Arguments
405    ///
406    /// - `T` - The custom payload data to set.
407    ///
408    /// # Returns
409    ///
410    /// - `&mut Self` - The modified instance for chaining.
411    pub fn set_custom(&mut self, custom: T) -> &mut Self {
412        self.custom = custom;
413        self
414    }
415
416    /// Returns a reference to the subject.
417    ///
418    /// # Returns
419    ///
420    /// - `&String` - The subject.
421    pub fn get_sub(&self) -> &String {
422        &self.sub
423    }
424
425    /// Sets the subject.
426    ///
427    /// # Arguments
428    ///
429    /// - `AsRef<str>` - The subject to set.
430    ///
431    /// # Returns
432    ///
433    /// - `&mut Self` - The modified instance for chaining.
434    pub fn set_sub<S>(&mut self, sub: S) -> &mut Self
435    where
436        S: AsRef<str>,
437    {
438        self.sub = sub.as_ref().to_string();
439        self
440    }
441
442    /// Returns a reference to the issuer.
443    ///
444    /// # Returns
445    ///
446    /// - `&String` - The issuer.
447    pub fn get_iss(&self) -> &String {
448        &self.iss
449    }
450
451    /// Sets the issuer.
452    ///
453    /// # Arguments
454    ///
455    /// - `AsRef<str>` - The issuer to set.
456    ///
457    /// # Returns
458    ///
459    /// - `&mut Self` - The modified instance for chaining.
460    pub fn set_iss<S>(&mut self, iss: S) -> &mut Self
461    where
462        S: AsRef<str>,
463    {
464        self.iss = iss.as_ref().to_string();
465        self
466    }
467
468    /// Returns the expiration time.
469    ///
470    /// # Returns
471    ///
472    /// - `usize` - The expiration timestamp.
473    pub fn get_exp(&self) -> usize {
474        self.exp
475    }
476
477    /// Sets the expiration time.
478    ///
479    /// # Arguments
480    ///
481    /// - `exp` - The expiration timestamp to set.
482    ///
483    /// # Returns
484    ///
485    /// - `&mut Self` - The modified instance for chaining.
486    pub fn set_exp(&mut self, exp: usize) -> &mut Self {
487        self.exp = exp;
488        self
489    }
490
491    /// Returns the issued at time.
492    ///
493    /// # Returns
494    ///
495    /// - `usize` - The issued at timestamp.
496    pub fn get_iat(&self) -> usize {
497        self.iat
498    }
499
500    /// Sets the issued at time.
501    ///
502    /// # Arguments
503    ///
504    /// - `usize` - The issued at timestamp to set.
505    ///
506    /// # Returns
507    ///
508    /// - `&mut Self` - The modified instance for chaining.
509    pub fn set_iat(&mut self, iat: usize) -> &mut Self {
510        self.iat = iat;
511        self
512    }
513}
514
515impl ExtraJwtClaims {
516    /// Creates a new ExtraJwtClaims instance.
517    ///
518    /// # Arguments
519    ///
520    /// - `AsRef<str>` - The subject (user identifier).
521    /// - `AsRef<str>` - The issuer.
522    /// - `usize` - Expiration time as a Unix timestamp.
523    ///
524    /// # Returns
525    ///
526    /// - `ExtraJwtClaims` - The created claims instance.
527    pub fn new<S>(sub: S, iss: S, exp: usize) -> Self
528    where
529        S: AsRef<str>,
530    {
531        let now: usize = SystemTime::now()
532            .duration_since(UNIX_EPOCH)
533            .unwrap_or_default()
534            .as_secs() as usize;
535        Self {
536            sub: sub.as_ref().to_string(),
537            iss: iss.as_ref().to_string(),
538            exp,
539            iat: now,
540            extra: HashMap::new(),
541        }
542    }
543
544    /// Returns a reference to the subject.
545    ///
546    /// # Returns
547    ///
548    /// - `&String` - The subject.
549    pub fn get_sub(&self) -> &String {
550        &self.sub
551    }
552
553    /// Sets the subject.
554    ///
555    /// # Arguments
556    ///
557    /// - `AsRef<str>` - The subject to set.
558    ///
559    /// # Returns
560    ///
561    /// - `&mut Self` - The modified instance for chaining.
562    pub fn set_sub<S>(&mut self, sub: S) -> &mut Self
563    where
564        S: AsRef<str>,
565    {
566        self.sub = sub.as_ref().to_string();
567        self
568    }
569
570    /// Returns a reference to the issuer.
571    ///
572    /// # Returns
573    ///
574    /// - `&String` - The issuer.
575    pub fn get_iss(&self) -> &String {
576        &self.iss
577    }
578
579    /// Sets the issuer.
580    ///
581    /// # Arguments
582    ///
583    /// - `AsRef<str>` - The issuer to set.
584    ///
585    /// # Returns
586    ///
587    /// - `&mut Self` - The modified instance for chaining.
588    pub fn set_iss<S>(&mut self, iss: S) -> &mut Self
589    where
590        S: AsRef<str>,
591    {
592        self.iss = iss.as_ref().to_string();
593        self
594    }
595
596    /// Returns the expiration time.
597    ///
598    /// # Returns
599    ///
600    /// - `usize` - The expiration timestamp.
601    pub fn get_exp(&self) -> usize {
602        self.exp
603    }
604
605    /// Sets the expiration time.
606    ///
607    /// # Arguments
608    ///
609    /// - `exp` - The expiration timestamp to set.
610    ///
611    /// # Returns
612    ///
613    /// - `&mut Self` - The modified instance for chaining.
614    pub fn set_exp(&mut self, exp: usize) -> &mut Self {
615        self.exp = exp;
616        self
617    }
618
619    /// Returns the issued at time.
620    ///
621    /// # Returns
622    ///
623    /// - `usize` - The issued at timestamp.
624    pub fn get_iat(&self) -> usize {
625        self.iat
626    }
627
628    /// Sets the issued at time.
629    ///
630    /// # Arguments
631    ///
632    /// - `usize` - The issued at timestamp to set.
633    ///
634    /// # Returns
635    ///
636    /// - `&mut Self` - The modified instance for chaining.
637    pub fn set_iat(&mut self, iat: usize) -> &mut Self {
638        self.iat = iat;
639        self
640    }
641
642    /// Returns a reference to the extra claims.
643    ///
644    /// # Returns
645    ///
646    /// - `&HashMap<String, Value>` - The extra claims.
647    pub fn get_extra(&self) -> &HashMap<String, Value> {
648        &self.extra
649    }
650
651    /// Returns a mutable reference to the extra claims.
652    ///
653    /// # Returns
654    ///
655    /// - `&mut HashMap<String, Value>` - The mutable extra claims.
656    pub fn get_mut_extra(&mut self) -> &mut HashMap<String, Value> {
657        &mut self.extra
658    }
659
660    /// Sets the extra claims.
661    ///
662    /// # Arguments
663    ///
664    /// - `HashMap<String, Value>` - The extra claims to set.
665    ///
666    /// # Returns
667    ///
668    /// - `&mut Self` - The modified instance for chaining.
669    pub fn set_extra(&mut self, extra: HashMap<String, Value>) -> &mut Self {
670        self.extra = extra;
671        self
672    }
673}
674
675/// Display implementation for JwtValidationError.
676impl std::fmt::Display for JwtValidationError {
677    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
678        match self {
679            Self::Expired => write!(f, "Token has expired"),
680            Self::InvalidSignature => write!(f, "Invalid token signature"),
681            Self::InvalidIssuer => write!(f, "Invalid token issuer"),
682            Self::InvalidSubject => write!(f, "Invalid token subject"),
683            Self::NotYetValid => write!(f, "Token is not yet valid"),
684            Self::Malformed => write!(f, "Malformed token"),
685            Self::Other(msg) => write!(f, "{msg}"),
686        }
687    }
688}
689
690/// Error trait implementation for JwtValidationError.
691impl std::error::Error for JwtValidationError {}
692
693/// Conversion from jsonwebtoken errors to JwtValidationError.
694///
695/// # Arguments
696///
697/// - `jsonwebtoken::errors::Error` - The jsonwebtoken error to convert.
698///
699/// # Returns
700///
701/// - `JwtValidationError` - The corresponding validation error.
702impl From<jsonwebtoken::errors::Error> for JwtValidationError {
703    fn from(error: jsonwebtoken::errors::Error) -> Self {
704        match error.kind() {
705            jsonwebtoken::errors::ErrorKind::ExpiredSignature => Self::Expired,
706            jsonwebtoken::errors::ErrorKind::InvalidSignature => Self::InvalidSignature,
707            jsonwebtoken::errors::ErrorKind::InvalidIssuer => Self::InvalidIssuer,
708            jsonwebtoken::errors::ErrorKind::InvalidSubject => Self::InvalidSubject,
709            jsonwebtoken::errors::ErrorKind::ImmatureSignature => Self::NotYetValid,
710            _ => Self::Other(error.to_string()),
711        }
712    }
713}
714
715/// Implementation block for JwtConfig.
716impl JwtConfig {
717    /// Creates a new JwtConfig instance with the specified settings.
718    ///
719    /// # Arguments
720    ///
721    /// - `String` - The secret key for signing tokens.
722    /// - `u64` - Token validity duration in seconds.
723    /// - `String` - The issuer identifier for the token.
724    ///
725    /// # Returns
726    ///
727    /// - `JwtConfig` - The configured JwtConfig instance.
728    pub fn with_settings(secret: String, expiration_seconds: u64, issuer: String) -> Self {
729        let mut instance: JwtConfig = Self::default();
730        instance
731            .set_secret(secret)
732            .set_expiration_seconds(expiration_seconds)
733            .set_issuer(issuer);
734        instance
735    }
736}
737
738/// Conversion from JwtConfig to JwtService.
739///
740/// # Arguments
741///
742/// - `JwtConfig` - The JWT configuration to convert.
743///
744/// # Returns
745///
746/// - `JwtService` - The initialized JWT service.
747impl From<JwtConfig> for JwtService {
748    fn from(config: JwtConfig) -> Self {
749        let encoding_key: EncodingKey = EncodingKey::from_secret(config.get_secret().as_bytes());
750        let decoding_key: DecodingKey = DecodingKey::from_secret(config.get_secret().as_bytes());
751        let mut validation: Validation = Validation::new(Algorithm::HS256);
752        validation.set_issuer(&[config.get_issuer()]);
753        Self::new(config, encoding_key, decoding_key, validation)
754    }
755}
756
757/// Implementation block for JwtService core functionality.
758impl JwtService {
759    /// Generates a JWT token for the given subject.
760    ///
761    /// # Arguments
762    ///
763    /// - `AsRef<str>` - The subject (user identifier) to include in the token.
764    ///
765    /// # Returns
766    ///
767    /// - `Result<JwtToken, String>` - The generated token on success, or an error message on failure.
768    pub fn generate_token<S>(&self, subject: S) -> Result<JwtToken, String>
769    where
770        S: AsRef<str>,
771    {
772        let now: usize = SystemTime::now()
773            .duration_since(UNIX_EPOCH)
774            .unwrap_or_default()
775            .as_secs() as usize;
776        let exp: usize = now + self.get_config().get_expiration_seconds() as usize;
777        let claims: JwtExtraJwtClaims = JwtExtraJwtClaims::new(
778            subject.as_ref().to_string(),
779            self.get_config().get_issuer().clone(),
780            exp,
781            now,
782            now,
783        );
784        let token: String = encode(
785            &Header::new(Algorithm::HS256),
786            &claims,
787            self.get_encoding_key(),
788        )
789        .map_err(|error| error.to_string())?;
790        let mut jwt_token: JwtToken = JwtToken::default();
791        jwt_token
792            .set_token(token)
793            .set_token_type(BEARER)
794            .set_expires_in(self.get_config().get_expiration_seconds());
795        Ok(jwt_token)
796    }
797
798    /// Validates a JWT token and returns its claims.
799    ///
800    /// # Arguments
801    ///
802    /// - `AsRef<str>` - The JWT token to validate.
803    ///
804    /// # Returns
805    ///
806    /// - `Result<JwtExtraJwtClaims, JwtValidationError>` - The claims on success, or a validation error on failure.
807    pub fn validate_token<T>(&self, token: T) -> Result<JwtExtraJwtClaims, JwtValidationError>
808    where
809        T: AsRef<str>,
810    {
811        let token_data = decode::<JwtExtraJwtClaims>(
812            token.as_ref(),
813            self.get_decoding_key(),
814            self.get_validation(),
815        )?;
816        Ok(token_data.claims)
817    }
818
819    /// Extracts the subject from a JWT token.
820    ///
821    /// # Arguments
822    ///
823    /// - `AsRef<str>` - The JWT token to extract the subject from.
824    ///
825    /// # Returns
826    ///
827    /// - `Result<String, String>` - The subject on success, or an error message on failure.
828    pub fn get_subject_from_token<T>(&self, token: T) -> Result<String, String>
829    where
830        T: AsRef<str>,
831    {
832        let claims: JwtExtraJwtClaims = self.validate_token(token).map_err(|e| e.to_string())?;
833        Ok(claims.get_sub().clone())
834    }
835
836    /// Checks if a JWT token is expired.
837    ///
838    /// # Arguments
839    ///
840    /// - `AsRef<str>` - The JWT token to check.
841    ///
842    /// # Returns
843    ///
844    /// - `Result<bool, String>` - True if expired, false otherwise, or an error message on failure.
845    pub fn is_token_expired<T>(&self, token: T) -> Result<bool, String>
846    where
847        T: AsRef<str>,
848    {
849        match decode::<JwtExtraJwtClaims>(
850            token.as_ref(),
851            self.get_decoding_key(),
852            &Validation::new(Algorithm::HS256),
853        ) {
854            Ok(token_data) => {
855                let now: usize = SystemTime::now()
856                    .duration_since(UNIX_EPOCH)
857                    .unwrap_or_default()
858                    .as_secs() as usize;
859                Ok(token_data.claims.get_exp() < now)
860            }
861            Err(error) => Err(error.to_string()),
862        }
863    }
864}
865
866/// Implementation block for JwtService with custom claims support.
867impl JwtService {
868    /// Generates a JWT token with custom claims.
869    ///
870    /// # Arguments
871    ///
872    /// - `AsRef<str>` - The subject (user identifier) to include in the token.
873    /// - `Clone + Default + Serialize + for<'de> Deserialize<'de>` - The custom claims to include in the token payload.
874    ///
875    /// # Returns
876    ///
877    /// - `Result<JwtToken, String>` - The generated token on success, or an error message on failure.
878    pub fn generate_token_with_claims<U, S>(
879        &self,
880        subject: S,
881        claims: U,
882    ) -> Result<JwtToken, String>
883    where
884        U: Clone + Default + Serialize + for<'de> Deserialize<'de>,
885        S: AsRef<str>,
886    {
887        let now: usize = SystemTime::now()
888            .duration_since(UNIX_EPOCH)
889            .unwrap_or_default()
890            .as_secs() as usize;
891        let mut res_claims: CustomExtraJwtClaims<U> = CustomExtraJwtClaims::default();
892        res_claims
893            .set_custom(claims)
894            .set_sub(subject.as_ref())
895            .set_iss(self.get_config().get_issuer().clone())
896            .set_exp(now + self.get_config().get_expiration_seconds() as usize)
897            .set_iat(now);
898        let token: String = encode(
899            &Header::new(Algorithm::HS256),
900            &res_claims,
901            self.get_encoding_key(),
902        )
903        .map_err(|error| error.to_string())?;
904        let mut jwt_token: JwtToken = JwtToken::default();
905        jwt_token.set_token(token);
906        jwt_token.set_token_type(BEARER);
907        jwt_token.set_expires_in(self.get_config().get_expiration_seconds());
908        Ok(jwt_token)
909    }
910
911    /// Validates a JWT token and returns its custom claims.
912    ///
913    /// # Arguments
914    ///
915    /// - `AsRef<str>` - The JWT token to validate.
916    ///
917    /// # Returns
918    ///
919    /// - `Result<CustomExtraJwtClaims<U>, JwtValidationError>` - The custom claims on success, or a validation error on failure.
920    pub fn validate_token_with_claims<U, T>(
921        &self,
922        token: T,
923    ) -> Result<CustomExtraJwtClaims<U>, JwtValidationError>
924    where
925        U: Clone + Default + Serialize + for<'de> Deserialize<'de>,
926        T: AsRef<str>,
927    {
928        let token_data: TokenData<CustomExtraJwtClaims<U>> = decode::<CustomExtraJwtClaims<U>>(
929            token.as_ref(),
930            self.get_decoding_key(),
931            self.get_validation(),
932        )?;
933        Ok(token_data.claims)
934    }
935
936    /// Generates a JWT token with extra custom fields.
937    ///
938    /// # Arguments
939    ///
940    /// - `AsRef<str>` - The subject (user identifier) to include in the token.
941    /// - `HashMap<String, Value>` - Additional key-value pairs to include in the token payload.
942    ///
943    /// # Returns
944    ///
945    /// - `Result<JwtToken, String>` - The generated token on success, or an error message on failure.
946    pub fn generate_token_with_extra_claims<S>(
947        &self,
948        subject: S,
949        extra: HashMap<String, Value>,
950    ) -> Result<JwtToken, String>
951    where
952        S: AsRef<str>,
953    {
954        let now: usize = SystemTime::now()
955            .duration_since(UNIX_EPOCH)
956            .unwrap_or_default()
957            .as_secs() as usize;
958        let mut claims: ExtraJwtClaims = ExtraJwtClaims::new(
959            subject.as_ref().to_string(),
960            self.get_config().get_issuer().clone(),
961            now + self.get_config().get_expiration_seconds() as usize,
962        );
963        claims.set_extra(extra);
964        let token: String = encode(
965            &Header::new(Algorithm::HS256),
966            &claims,
967            self.get_encoding_key(),
968        )
969        .map_err(|error| error.to_string())?;
970        let mut jwt_token: JwtToken = JwtToken::default();
971        jwt_token.set_token(token);
972        jwt_token.set_token_type(BEARER);
973        jwt_token.set_expires_in(self.get_config().get_expiration_seconds());
974        Ok(jwt_token)
975    }
976
977    /// Validates a JWT token and returns its claims with extra fields.
978    ///
979    /// # Arguments
980    ///
981    /// - `AsRef<str>` - The JWT token to validate.
982    ///
983    /// # Returns
984    ///
985    /// - `Result<ExtraJwtClaims, JwtValidationError>` - The claims with extra fields on success, or a validation error on failure.
986    pub fn validate_token_with_extra_claims<T>(
987        &self,
988        token: T,
989    ) -> Result<ExtraJwtClaims, JwtValidationError>
990    where
991        T: AsRef<str>,
992    {
993        let token_data: TokenData<ExtraJwtClaims> = decode::<ExtraJwtClaims>(
994            token.as_ref(),
995            self.get_decoding_key(),
996            self.get_validation(),
997        )?;
998        Ok(token_data.claims)
999    }
1000
1001    /// Extracts a specific field value from a JWT token's extra claims.
1002    ///
1003    /// # Arguments
1004    ///
1005    /// - `AsRef<str>` - The JWT AsRef<str token to extract the field from.
1006    /// - `AsRef<str>` - The key of the field to retrieve.
1007    ///
1008    /// # Returns
1009    ///
1010    /// - `Result<Option<Value>, JwtValidationError>` - The field value if found, or None, or a validation error.
1011    pub fn get_from_token<T, K>(
1012        &self,
1013        token: T,
1014        field_key: K,
1015    ) -> Result<Option<Value>, JwtValidationError>
1016    where
1017        T: AsRef<str>,
1018        K: AsRef<str>,
1019    {
1020        let claims: ExtraJwtClaims = self.validate_token_with_extra_claims(token)?;
1021        Ok(claims.get(field_key.as_ref()).cloned())
1022    }
1023}
1024
1025/// Implementation block for ExtraJwtClaims helper methods.
1026impl ExtraJwtClaims {
1027    /// Inserts a key-value pair into the extra claims.
1028    ///
1029    /// # Arguments
1030    ///
1031    /// - `String` - The key to insert.
1032    /// - `Value` - The value to associate with the key.
1033    ///
1034    /// # Returns
1035    ///
1036    /// - `Self` - The modified ExtraJwtClaims instance for chaining.
1037    pub fn insert(mut self, key: String, value: Value) -> Self {
1038        self.get_mut_extra().insert(key, value);
1039        self
1040    }
1041
1042    /// Extends the extra claims with additional key-value pairs.
1043    ///
1044    /// # Arguments
1045    ///
1046    /// - `HashMap<String, Value>` - A HashMap of key-value pairs to add.
1047    ///
1048    /// # Returns
1049    ///
1050    /// - `Self` - The modified ExtraJwtClaims instance for chaining.
1051    pub fn extend_extra(mut self, extra: HashMap<String, Value>) -> Self {
1052        self.get_mut_extra().extend(extra);
1053        self
1054    }
1055
1056    /// Retrieves a value from the extra claims by key.
1057    ///
1058    /// # Arguments
1059    ///
1060    /// - `AsRef<str>` - The key to look up.
1061    ///
1062    /// # Returns
1063    ///
1064    /// - `Option<&Value>` - The value if found, or None.
1065    pub fn get<K>(&self, key: K) -> Option<&Value>
1066    where
1067        K: AsRef<str>,
1068    {
1069        self.get_extra().get(key.as_ref())
1070    }
1071
1072    /// Checks if a key exists in the extra claims.
1073    ///
1074    /// # Arguments
1075    ///
1076    /// - `AsRef<str>` - The key to check.
1077    ///
1078    /// # Returns
1079    ///
1080    /// - `bool` - True if the key exists, false otherwise.
1081    pub fn contains_key<K>(&self, key: K) -> bool
1082    where
1083        K: AsRef<str>,
1084    {
1085        self.get_extra().contains_key(key.as_ref())
1086    }
1087
1088    /// Removes a key from the extra claims and returns its value.
1089    ///
1090    /// # Arguments
1091    ///
1092    /// - `AsRef<str>` - The key to remove.
1093    ///
1094    /// # Returns
1095    ///
1096    /// - `Option<Value>` - The removed value if found, or None.
1097    pub fn remove<K>(&mut self, key: K) -> Option<Value>
1098    where
1099        K: AsRef<str>,
1100    {
1101        self.get_mut_extra().remove(key.as_ref())
1102    }
1103}