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}