diff --git a/Cargo.lock b/Cargo.lock index 92643bd..a670689 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -296,12 +296,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" -[[package]] -name = "dtoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" - [[package]] name = "either" version = "1.6.1" @@ -326,7 +320,6 @@ dependencies = [ "atomic", "pear", "serde", - "serde_yaml", "toml", "uncased", "version_check", @@ -648,12 +641,6 @@ version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765" -[[package]] -name = "linked-hash-map" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" - [[package]] name = "lock_api" version = "0.4.4" @@ -1198,7 +1185,6 @@ dependencies = [ "chrono", "diesel", "diesel_migrations", - "figment", "hmac", "jwt", "openssl", @@ -1284,18 +1270,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_yaml" -version = "0.8.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039ba818c784248423789eec090aab9fb566c7b94d6ebbfa1814a9fd52c8afb2" -dependencies = [ - "dtoa", - "linked-hash-map", - "serde", - "yaml-rust", -] - [[package]] name = "sha1" version = "0.6.0" @@ -1764,15 +1738,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - [[package]] name = "yansi" version = "0.5.0" diff --git a/Cargo.toml b/Cargo.toml index 5b80483..ff6ac33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,8 +34,6 @@ sha2 = "*" chrono = { version = "*", features = [ "serde" ] } # Encoding of refresh tokens base64 = "0.13.0" -# Reading in configuration files -figment = { version = "*", features = [ "yaml" ] } [profile.release] lto = true diff --git a/Rb.yaml b/Rb.yaml deleted file mode 100644 index 6b40537..0000000 --- a/Rb.yaml +++ /dev/null @@ -1,23 +0,0 @@ -default: - address: "0.0.0.0" - ports: 8000 - -debug: - keep_alive: 5 - read_timeout: 5 - write_timeout: 5 - log_level: "normal" - limits: - forms: 32768 - - admin_user: "admin" - admin_pass: "password" - jwt: - key: "secret" - refresh_token_size: 64 - # Just 5 seconds for debugging - refresh_token_expire: 5 - - databases: - postgres_rb: - url: "postgres://rb:rb@localhost:5432/rb" diff --git a/Rocket.toml b/Rocket.toml new file mode 100644 index 0000000..e931e4d --- /dev/null +++ b/Rocket.toml @@ -0,0 +1,13 @@ +[debug] +port = 8000 +keep_alive = 5 +read_timeout = 5 +write_timeout = 5 +log_level = "normal" +limits = { forms = 32768 } + +[debug.databases] +postgres_rb = { url = "postgres://rb:rb@localhost:5432/rb" } + +[release.databases] +postgres_rb = { url = "postgres://rb:rb@localhost:5432/rb" } diff --git a/src/auth/jwt.rs b/src/auth/jwt.rs index 89ce734..83e7a1e 100644 --- a/src/auth/jwt.rs +++ b/src/auth/jwt.rs @@ -11,7 +11,6 @@ use crate::{ db::{tokens::NewRefreshToken, users::User}, errors::{RbError, RbResult}, schema::{refresh_tokens::dsl as refresh_tokens, users::dsl as users}, - RbJwtConf, }; #[derive(Serialize)] @@ -31,13 +30,10 @@ pub struct Claims pub exp: i64, } -pub fn generate_jwt_token( - conn: &PgConnection, - jwt: &RbJwtConf, - user: &User, -) -> RbResult +pub fn generate_jwt_token(conn: &PgConnection, user: &User) -> RbResult { - let key: Hmac = Hmac::new_from_slice(jwt.key.as_bytes()) + let secret = std::env::var("JWT_KEY").map_err(|_| RbError::Custom("Missing JWT key."))?; + let key: Hmac = Hmac::new_from_slice(secret.as_bytes()) .map_err(|_| RbError::Custom("Couldn't create Hmac key."))?; let current_time = Utc::now(); @@ -47,7 +43,7 @@ pub fn generate_jwt_token( id: user.id, username: user.username.clone(), admin: user.admin, - exp: current_time.timestamp() + jwt.refresh_token_expire, + exp: current_time.timestamp() + crate::JWT_EXP_SECONDS, }; // Sign the claims into a new token @@ -56,11 +52,11 @@ pub fn generate_jwt_token( .map_err(|_| RbError::Custom("Couldn't sign JWT."))?; // Generate a random refresh token - let mut refresh_token = vec![0u8; jwt.refresh_token_size]; + let mut refresh_token = [0u8; crate::REFRESH_TOKEN_N_BYTES]; thread_rng().fill(&mut refresh_token[..]); let refresh_expire = - (current_time + chrono::Duration::seconds(jwt.refresh_token_expire)).naive_utc(); + (current_time + chrono::Duration::seconds(crate::REFRESH_TOKEN_EXP_SECONDS)).naive_utc(); // Store refresh token in database db::tokens::create( @@ -78,11 +74,7 @@ pub fn generate_jwt_token( }) } -pub fn refresh_token( - conn: &PgConnection, - jwt: &RbJwtConf, - refresh_token: &str, -) -> RbResult +pub fn refresh_token(conn: &PgConnection, refresh_token: &str) -> RbResult { let token_bytes = base64::decode(refresh_token).map_err(|_| RbError::AuthInvalidRefreshToken)?; @@ -116,5 +108,5 @@ pub fn refresh_token( .execute(conn) .map_err(|_| RbError::Custom("Couldn't update last used time."))?; - generate_jwt_token(conn, jwt, &user) + generate_jwt_token(conn, &user) } diff --git a/src/auth/mod.rs b/src/auth/mod.rs index 78a4fa0..b4cbf0f 100644 --- a/src/auth/mod.rs +++ b/src/auth/mod.rs @@ -1,11 +1,11 @@ -use rocket::{serde::json::Json, State}; +use rocket::serde::json::Json; use serde::Deserialize; use self::{ jwt::{generate_jwt_token, JWTResponse}, pass::verify_user, }; -use crate::{errors::RbResult, guards::User, RbConfig, RbDbConn, RbJwtConf}; +use crate::{errors::RbResult, guards::User, RbDbConn}; pub mod jwt; pub mod pass; @@ -24,24 +24,16 @@ pub async fn already_logged_in(_user: User) -> String } #[post("/login", data = "", rank = 2)] -pub async fn login( - conn: RbDbConn, - conf: &State, - credentials: Json, -) -> RbResult> +pub async fn login(conn: RbDbConn, credentials: Json) -> RbResult> { let credentials = credentials.into_inner(); - let jwt = conf.jwt.clone(); // Get the user, if credentials are valid let user = conn .run(move |c| verify_user(c, &credentials.username, &credentials.password)) .await?; - Ok(Json( - conn.run(move |c| generate_jwt_token(c, &jwt, &user)) - .await?, - )) + Ok(Json(conn.run(move |c| generate_jwt_token(c, &user)).await?)) } #[derive(Deserialize)] @@ -54,15 +46,13 @@ pub struct RefreshTokenRequest #[post("/refresh", data = "")] pub async fn refresh_token( conn: RbDbConn, - conf: &State, refresh_token_request: Json, ) -> RbResult> { let refresh_token = refresh_token_request.into_inner().refresh_token; - let jwt = conf.jwt.clone(); Ok(Json( - conn.run(move |c| crate::auth::jwt::refresh_token(c, &jwt, &refresh_token)) + conn.run(move |c| crate::auth::jwt::refresh_token(c, &refresh_token)) .await?, )) } diff --git a/src/main.rs b/src/main.rs index fa147e9..400c0e8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,13 +8,8 @@ extern crate diesel_migrations; #[macro_use] extern crate diesel; -use figment::{ - providers::{Env, Format, Yaml}, - Figment, -}; use rocket::{fairing::AdHoc, Build, Rocket}; use rocket_sync_db_pools::database; -use serde::{Deserialize, Serialize}; mod admin; pub mod auth; @@ -23,6 +18,14 @@ pub mod errors; pub mod guards; pub(crate) mod schema; +// Any import defaults are defined here +/// Expire time for the JWT tokens in seconds. +const JWT_EXP_SECONDS: i64 = 600; +/// 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 = 604800; + #[database("postgres_rb")] pub struct RbDbConn(diesel::PgConnection); @@ -57,37 +60,16 @@ async fn create_admin_user(rocket: Rocket) -> Result, Rocke Ok(rocket) } -#[derive(Debug, Deserialize, Serialize, Clone)] -pub struct RbJwtConf -{ - key: String, - refresh_token_size: usize, - refresh_token_expire: i64, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct RbConfig -{ - admin_user: String, - admin_pass: String, - jwt: RbJwtConf, -} - #[launch] fn rocket() -> _ { - let figment = Figment::from(rocket::config::Config::default()) - .merge(Yaml::file("Rb.yaml").nested()) - .merge(Env::prefixed("RB_").global()); - - rocket::custom(figment) + rocket::build() .attach(RbDbConn::fairing()) .attach(AdHoc::try_on_ignite( "Run database migrations", run_db_migrations, )) .attach(AdHoc::try_on_ignite("Create admin user", create_admin_user)) - .attach(AdHoc::config::()) .mount( "/api/auth", routes![auth::already_logged_in, auth::login, auth::refresh_token,],