forked from Chewing_Bever/rusty-bever
				
			First successful JWT token request achieved
							parent
							
								
									0d4d96d761
								
							
						
					
					
						commit
						13259249fd
					
				|  | @ -155,6 +155,7 @@ dependencies = [ | |||
|  "libc", | ||||
|  "num-integer", | ||||
|  "num-traits", | ||||
|  "serde", | ||||
|  "time 0.1.44", | ||||
|  "winapi", | ||||
| ] | ||||
|  | @ -252,6 +253,7 @@ checksum = "bba51ca66f57261fd17cadf8b73e4775cc307d0521d855de3f5de91a8f074e0e" | |||
| dependencies = [ | ||||
|  "bitflags", | ||||
|  "byteorder", | ||||
|  "chrono", | ||||
|  "diesel_derives", | ||||
|  "pq-sys", | ||||
|  "r2d2", | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ path = "src/rbs/main.rs" | |||
| 
 | ||||
| [dependencies] | ||||
| # ORM | ||||
| diesel = { version = "1.4.7", features = ["postgres", "uuidv07"] } | ||||
| diesel = { version = "1.4.7", features = ["postgres", "uuidv07", "chrono"] } | ||||
| diesel_migrations = "1.4.0" | ||||
| # To properly compile libpq statically | ||||
| openssl = "0.10.36" | ||||
|  | @ -27,7 +27,7 @@ uuid = { version = "0.8.2", features = ["serde"] } | |||
| jwt = "0.14.0" | ||||
| hmac = "*" | ||||
| sha2 = "*" | ||||
| chrono = "0.4.19" | ||||
| chrono = { version = "*", features = [ "serde" ] } | ||||
| base64 = "0.13.0" | ||||
| 
 | ||||
| # Backend web framework | ||||
|  |  | |||
|  | @ -17,6 +17,14 @@ use std::collections::HashMap; | |||
| const JWT_EXP_SECONDS: i64 = 900; | ||||
| /// Amount of bytes the refresh tokens should consist of
 | ||||
| const REFRESH_TOKEN_N_BYTES: usize = 64; | ||||
| /// Expire time for refresh tokens; here: one week
 | ||||
| const REFRESH_TOKEN_EXP_SECONDS: i64 = 36288000; | ||||
| 
 | ||||
| fn log<T>(message: &str, o: T) -> T { | ||||
|     println!("{}", message); | ||||
| 
 | ||||
|     o | ||||
| } | ||||
| 
 | ||||
| pub fn verify_user(conn: &PgConnection, username: &str, password: &str) -> crate::Result<User> { | ||||
|     // TODO handle non-"NotFound" Diesel errors accordingely
 | ||||
|  | @ -46,7 +54,9 @@ pub struct JWTResponse { | |||
| pub fn generate_jwt_token(conn: &PgConnection, user: &User) -> crate::Result<JWTResponse> { | ||||
|     // TODO actually use proper secret here
 | ||||
|     let key: Hmac<Sha256> = | ||||
|         Hmac::new_from_slice(b"some-secret").map_err(|_| RBError::JWTCreationError)?; | ||||
|         Hmac::new_from_slice(b"some-secret").map_err(|_| log("Failed to create key", RBError::JWTCreationError))?; | ||||
| 
 | ||||
|     let current_time = Utc::now(); | ||||
| 
 | ||||
|     // Create the claims
 | ||||
|     let mut claims = HashMap::new(); | ||||
|  | @ -55,23 +65,27 @@ pub fn generate_jwt_token(conn: &PgConnection, user: &User) -> crate::Result<JWT | |||
|     claims.insert("admin", user.admin.to_string()); | ||||
|     claims.insert( | ||||
|         "exp", | ||||
|         (Utc::now().timestamp() + JWT_EXP_SECONDS).to_string(), | ||||
|         (current_time.timestamp() + JWT_EXP_SECONDS).to_string(), | ||||
|     ); | ||||
| 
 | ||||
|     // Sign the claims into a new token
 | ||||
|     let token = claims | ||||
|         .sign_with_key(&key) | ||||
|         .map_err(|_| RBError::JWTCreationError)?; | ||||
|         .map_err(|_| log("Failed to sign token", RBError::JWTCreationError))?; | ||||
| 
 | ||||
|     // Generate a random refresh token
 | ||||
|     let mut refresh_token = [0u8; REFRESH_TOKEN_N_BYTES]; | ||||
|     thread_rng().fill(&mut refresh_token[..]); | ||||
| 
 | ||||
|     let refresh_expire = (current_time + chrono::Duration::seconds(REFRESH_TOKEN_EXP_SECONDS)).naive_utc(); | ||||
| 
 | ||||
|     // Store refresh token in database
 | ||||
|     // TODO add expires_at here (it's what's causing the errors)
 | ||||
|     insert_into(refresh_tokens::refresh_tokens) | ||||
|         .values(NewRefreshToken { | ||||
|             token: refresh_token.to_vec(), | ||||
|             user_id: user.id, | ||||
|             expires_at: refresh_expire | ||||
|         }) | ||||
|         .execute(conn) | ||||
|         .map_err(|_| RBError::JWTCreationError)?; | ||||
|  | @ -94,7 +108,6 @@ pub fn hash_password(password: &str) -> crate::Result<String> { | |||
| 
 | ||||
| pub fn create_admin_user(conn: &PgConnection, username: &str, password: &str) -> crate::Result<bool> { | ||||
|     let pass_hashed = hash_password(password)?; | ||||
|     println!("{}", pass_hashed); | ||||
|     let new_user = NewUser { | ||||
|             username: username.to_string(), | ||||
|             password: pass_hashed, | ||||
|  | @ -103,9 +116,9 @@ pub fn create_admin_user(conn: &PgConnection, username: &str, password: &str) -> | |||
| 
 | ||||
|     insert_into(users::users) | ||||
|         .values(&new_user) | ||||
|         // .on_conflict((users::username, users::password, users::admin))
 | ||||
|         // .do_update()
 | ||||
|         // .set(&new_user)
 | ||||
|         .on_conflict(users::username) | ||||
|         .do_update() | ||||
|         .set(&new_user) | ||||
|         .execute(conn).map_err(|_| RBError::AdminCreationError)?; | ||||
| 
 | ||||
|     Ok(true) | ||||
|  |  | |||
|  | @ -27,4 +27,5 @@ pub struct NewUser { | |||
| pub struct NewRefreshToken { | ||||
|     pub token: Vec<u8>, | ||||
|     pub user_id: Uuid, | ||||
|     pub expires_at: chrono::NaiveDateTime | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue