Last active
July 7, 2020 22:38
-
-
Save jrconlin/82ca1e6bf49f67dc71b8ac857484742c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use jsonwebtoken::{ | |
decode, encode, Algorithm, DecodingKey, EncodingKey, Header, TokenData, Validation, | |
}; | |
use serde::{Deserialize, Serialize}; | |
use std::convert::From; | |
use thiserror::Error; | |
#[derive(Error, Debug)] | |
pub enum TokenError { | |
#[error("Token is Invalid")] | |
InvalidToken, | |
#[error("Issuer is Invalid")] | |
InvalidIssuer, | |
#[error("some other error")] | |
Unknown, | |
} | |
// Just to clean up some of the code. This will auto-convert the | |
// error. Right now, it just returns "InvalidToken", but it should | |
// convert the error more appropriately. | |
impl From<jsonwebtoken::errors::Error> for TokenError { | |
fn from(err: jsonwebtoken::errors::Error) -> Self { | |
trace!("Original error {:?}", err); | |
Self::InvalidToken | |
} | |
} | |
#[derive(Debug, Serialize, Deserialize, PartialEq)] | |
pub struct Claims { | |
pub sub: String, | |
pub company: String, | |
pub iat: i64, | |
pub exp: i64, | |
} | |
pub fn verify_jwt_token(token: &str) -> Result<TokenData<Claims>, TokenError> { | |
let pub_key = include_bytes!("public_rsa_key.pem"); | |
decode::<Claims>( | |
&token, | |
&DecodingKey::from_rsa_pem(pub_key).unwrap(), | |
&Validation::new(Algorithm::RS256), | |
) | |
.map_err(From::from) | |
} | |
pub fn generate_token(my_claims: &Claims) -> Result<String, TokenError> { | |
let privkey_pem = include_bytes!("private_rsa_key.pem"); | |
encode( | |
&Header::new(Algorithm::RS256), | |
&my_claims, | |
&EncodingKey::from_rsa_pem(privkey_pem).unwrap(), | |
) | |
.map_err(From::from) | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
use chrono::{Local, Utc}; | |
#[test] | |
fn test_token() { | |
static THREE_DAYS: i64 = 60 * 60 * 24 * 3; | |
let now = Utc::now().timestamp_nanos() / 1_000_000_000; //nanoseconds -> seconds | |
println!( | |
"I think it's local:{:?} (UTC:{:?})", | |
Local::now(), | |
Utc::now() | |
); | |
let my_claims = Claims { | |
sub: "dummy_sub".to_string(), | |
company: "dummy_company".to_string(), | |
iat: now, | |
exp: now + THREE_DAYS, | |
}; | |
let token: String = generate_token(&my_claims).unwrap(); | |
println!("Original: {:?}", my_claims); | |
match verify_jwt_token(&token) { | |
Ok(value) => { | |
println!(" decoded: {:?}", value.claims); | |
assert!(value.claims == my_claims); | |
} | |
Err(err) => panic!("error: {}", err), | |
}; | |
} | |
#[test] | |
fn test_invalid_token() { | |
let token: String = String::from("bhxkgadweahfjhaweglfvawjcj"); | |
// Don't panic if you don't need to. | |
assert!(verify_jwt_token(&token).is_err()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment