rusty_jwt/
lib.rs

1use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, TokenData, Validation};
2use serde::{Deserialize, Serialize};
3use std::{
4    env,
5    error::Error,
6    io,
7    ops::Add,
8    time::{SystemTime, UNIX_EPOCH},
9};
10use uuid::Uuid;
11
12pub struct Cookie {}
13
14#[derive(Debug, Serialize, Deserialize)]
15pub struct Claims {
16    sub: String,
17    name: String,
18    email: String,
19    iat: u64,
20    exp: u64,
21}
22pub struct Users {
23    pub name: String,
24    pub email: String,
25    pub exp: u64,
26}
27impl Cookie {
28    /*
29    !encode
30    !takes two parameter secret and claims
31    !secret name like SECRET_NAME
32    !claims
33    !let claims = Claims {
34    !sub:auomatic generate,
35    !name:"USER_NAME",
36    !email:"USER_EMAIL",
37    !"iat":authomatic,
38    !"exp: eg: 3600 //1hour
39    !}
40
41    !encode the claims
42    !let cookie = Cookie::encode("SECRET_NAME", claims);
43    !eg eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaW5zdF9hdHRyaWJ1dGVzIjp7ImlhdCI6MTUxNjIzOTAyMn19.5f4dc9f2c5c9de145d528be2346f1bc1f8f63de53963bba6fcb41f648bc272e1
44    */
45    pub fn encode(secret: String, claims: Users) -> Result<String, Box<dyn Error>> {
46        let secret = env::var(secret);
47        //* secret checking
48        let claim = Claims {
49            sub: Uuid::new_v4().to_string(), //* generate uuid*/
50            name: claims.name,
51            //*user name
52            email: claims.email,
53            //*user email
54            iat: SystemTime::now()
55                .duration_since(UNIX_EPOCH)
56                .unwrap()
57                .as_secs(),
58            //* system time and format the time since 1997 and convert to seconds
59            exp: SystemTime::now()
60                .duration_since(UNIX_EPOCH)
61                .unwrap()
62                .as_secs()
63                .add(claims.exp),
64            //* system time and format the time since 1997 and convert to seconds and add the expiration time in seconds
65        };
66        match secret {
67            Ok(secret) => {
68                let encode_key = EncodingKey::from_secret(secret.as_bytes());
69                //* encoding the secret by converting the secret to bytes and and encoding the secret using h256 alogrithm so it can be easy to decode the secret the using same algorithm
70                let encode = encode(&Header::default(), &claim, &encode_key);
71                //*  encoded claims and setting the [header] as default
72                //* {
73                //* "alg": "HS256",
74                //* "typ": "JWT"
75                //* }
76                match encode {
77                    Ok(ecoded_cookie) => Ok(ecoded_cookie),
78                    Err(err) => Err(Box::new(io::Error::new(
79                        io::ErrorKind::InvalidData,
80                        err.to_string(),
81                    ))),
82                }
83            }
84            Err(err) => Err(Box::new(io::Error::new(
85                io::ErrorKind::InvalidData,
86                err.to_string(),
87            ))),
88        }
89        // Ok(())
90    }
91    /*
92    !decode cookie
93    !let decode = decode("SECRET_NAME",&cookie);
94    ! return claims and header
95    */
96    pub fn decode(secret: String, cookie: String) -> Result<TokenData<Claims>, Box<dyn Error>> {
97        let secret = env::var(secret);
98        match secret {
99            Ok(secret) => {
100                let decode_key = DecodingKey::from_secret(secret.as_bytes());
101                // * decoding the key using 256 sha algorithm
102                let decode = decode(
103                    &cookie,
104                    &decode_key,
105                    &Validation::new(jsonwebtoken::Algorithm::HS256),
106                );
107                // * decode the claims token and exract the claims and headers
108                match decode {
109                    Ok(decode) => Ok(decode),
110                    Err(err) => Err(Box::new(io::Error::new(
111                        io::ErrorKind::InvalidData,
112                        err.to_string(),
113                    ))),
114                }
115            }
116
117            Err(err) => Err(Box::new(io::Error::new(
118                io::ErrorKind::InvalidData,
119                err.to_string(),
120            ))),
121        }
122    }
123}