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