diff --git a/Cargo.lock b/Cargo.lock index bb2eba4..905e653 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1197,7 +1197,7 @@ dependencies = [ [[package]] name = "restapi" -version = "1.0.9" +version = "1.0.10" dependencies = [ "bb8", "bb8-postgres", diff --git a/Cargo.toml b/Cargo.toml index e8adb10..7dc30c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "restapi" description = "A secure-by-default rest api stack implemented with hyper, tokio, bb8 and postgres. This project is focused on providing end-to-end encryption by default for 12-factor applications looking to customize functionality using environment variables as needed. Includes a working user management and authentication backend written in postgresql with async S3 uploading for POST-ed data files." -version = "1.0.9" +version = "1.0.10" edition = "2021" license = "MIT" authors = [ diff --git a/src/handle_request.rs b/src/handle_request.rs index 114ded3..a62be86 100644 --- a/src/handle_request.rs +++ b/src/handle_request.rs @@ -1,3 +1,6 @@ +//! # Handle all Client Requests +//! + use std::convert::Infallible; use hyper::body; @@ -52,26 +55,24 @@ pub async fn handle_request( // Handle requests here - // elided: drop requests if 'accept' is not acceptable - // elided: handle OPTIONS requests - // elided: read session cookie and establish session - // elided: route to page - + /* + // + // debug client ciphers with this section + // let remote_addr = data.remote_addr.clone(); let cipher_suite = data.tls_info.clone().as_ref().unwrap().ciphersuite; - if false { - info!("\ - {tracking_label} - handle request - \ - uri={:?} \ - method={:?} \ - remote_addr={} \ - ciphers={:?}", - data.request.uri(), - data.request.method(), - remote_addr, - cipher_suite); - } + info!("\ + {tracking_label} - handle request - \ + uri={:?} \ + method={:?} \ + remote_addr={remote_addr} \ + ciphers={:?}", + data.request.uri(), + data.request.method(), + remote_addr, + cipher_suite); + */ let (parts, body) = data.request.into_parts(); let request_uri = parts.uri.path().clone(); diff --git a/src/jwt/api.rs b/src/jwt/api.rs index 94a7009..39ff3cc 100644 --- a/src/jwt/api.rs +++ b/src/jwt/api.rs @@ -1,46 +1,58 @@ -/// # JWT (json web tokens) -/// -/// ## Configurable JWT Environment Variables -/// -/// ### Header key for the token -/// -/// ```bash -/// export TOKEN_HEADER="Bearer" -/// ``` -/// -/// ### Token Org (embedded in the jwt) -/// -/// ```bash -/// export TOKEN_ORG="Org Name"; -/// ``` -/// -/// ### Token Lifetime Duration -/// -/// ```bash -/// # 30 days -/// export TOKEN_EXPIRATION_SECONDS_INTO_FUTURE=2592000; -/// # 7 days -/// export TOKEN_EXPIRATION_SECONDS_INTO_FUTURE=604800; -/// # 1 day -/// export TOKEN_EXPIRATION_SECONDS_INTO_FUTURE=86400; -/// ``` -/// -/// ### JWT Signing Keys -/// -/// ```bash -/// export TOKEN_ALGO_KEY_DIR="./jwt" -/// export TOKEN_ALGO_PRIVATE_KEY_ORG="${TOKEN_ALGO_KEY_DIR}/private-key.pem" -/// export TOKEN_ALGO_PRIVATE_KEY="${TOKEN_ALGO_KEY_DIR}/private-key-pkcs8.pem" -/// export TOKEN_ALGO_PUBLIC_KEY="${TOKEN_ALGO_KEY_DIR}/public-key.pem" -/// ``` -/// -/// generate your own jwt keys with these commands (bash) -/// -/// ```bash -/// openssl ecparam -name prime256v1 -genkey -out "${TOKEN_ALGO_PRIVATE_KEY_ORG}" -/// openssl pkcs8 -topk8 -nocrypt -in private-key.pem -out "${TOKEN_ALGO_PRIVATE_KEY}" -/// openssl ec -in "${TOKEN_ALGO_PRIVATE_KEY_ORG}" -pubout -out "${TOKEN_ALGO_PUBLIC_KEY}" -/// ``` +//! # JWT functions for creation and valiation +//! +//! Newly-created tokens are signed with the +//! private jwt key +//! (``TOKEN_ALGO_PRIVATE_KEY``) +//! and decoded with the public jwt key +//! (``TOKEN_ALGO_PUBLIC_KEY``). +//! +//! - [`create_token`](crate::jwt::api::create_token) +//! uses ``TOKEN_ALGO_PRIVATE_KEY`` +//! - [`validate_token`](crate::jwt::api::validate_token) +//! uses ``TOKEN_ALGO_PUBLIC_KEY`` +//! +//! ## Configurable JWT Environment Variables +//! +//! ### Header key for the token +//! +//! ```bash +//! export TOKEN_HEADER="Bearer" +//! ``` +//! +//! ### Token Org (embedded in the jwt) +//! +//! ```bash +//! export TOKEN_ORG="Org Name"; +//! ``` +//! +//! ### Token Lifetime Duration +//! +//! ```bash +//! # 30 days +//! export TOKEN_EXPIRATION_SECONDS_INTO_FUTURE=2592000; +//! # 7 days +//! export TOKEN_EXPIRATION_SECONDS_INTO_FUTURE=604800; +//! # 1 day +//! export TOKEN_EXPIRATION_SECONDS_INTO_FUTURE=86400; +//! ``` +//! +//! ### JWT Signing Keys +//! +//! ```bash +//! export TOKEN_ALGO_KEY_DIR="./jwt" +//! export TOKEN_ALGO_PRIVATE_KEY_ORG="${TOKEN_ALGO_KEY_DIR}/private-key.pem" +//! export TOKEN_ALGO_PRIVATE_KEY="${TOKEN_ALGO_KEY_DIR}/private-key-pkcs8.pem" +//! export TOKEN_ALGO_PUBLIC_KEY="${TOKEN_ALGO_KEY_DIR}/public-key.pem" +//! ``` +//! +//! generate your own jwt keys with these commands (bash) +//! +//! ```bash +//! openssl ecparam -name prime256v1 -genkey -out "${TOKEN_ALGO_PRIVATE_KEY_ORG}" +//! openssl pkcs8 -topk8 -nocrypt -in private-key.pem -out "${TOKEN_ALGO_PRIVATE_KEY}" +//! openssl ec -in "${TOKEN_ALGO_PRIVATE_KEY_ORG}" -pubout -out "${TOKEN_ALGO_PUBLIC_KEY}" +//! ``` +//! use serde::Deserialize; use serde::Serialize; @@ -83,8 +95,13 @@ pub struct TokenClaim { /// validate a decoded jwt token /// /// 1. create a token validator object -/// 2. decode the token by decrypting it using the -/// `decoding_key_bytes` and validate the contents +/// 2. decode the client's jwt with the +/// ``decoding_key_bytes`` +/// and validate the contents +/// +/// Change the decoding key with the +/// enviroment variable: +/// ``TOKEN_ALGO_PUBLIC_KEY`` /// /// # Returns /// @@ -172,7 +189,11 @@ pub async fn validate_token( /// get_current_timestamp /// -/// get the current unix epoch time as a `usize` +/// get the current unix epoch time as a ``usize`` +/// +/// # Returns +/// +/// ``usize`` /// pub fn get_current_timestamp() -> usize @@ -187,6 +208,10 @@ pub fn get_current_timestamp() /// determine when the jwt should expire in the future. /// and return it as a `usize` /// +/// # Returns +/// +/// ``usize`` +/// pub fn get_expiration_epoch_time( seconds_in_future: usize) -> usize @@ -197,13 +222,17 @@ pub fn get_expiration_epoch_time( /// get_token_org /// -/// wrapper for returning an env var `TOKEN_ORG` +/// wrapper for returning an env var ``TOKEN_ORG`` /// that can change the signed jwt contents for a /// custom organization name /// /// v2 this should move into the server statics: /// [`CoreConfig`](crate::core::core_config::CoreConfig) /// +/// # Returns +/// +/// ``String`` +/// pub fn get_token_org() -> String { @@ -215,13 +244,17 @@ pub fn get_token_org() /// get_token_expiration_in_seconds /// /// wrapper for returning an env var -/// `TOKEN_EXPIRATION_SECONDS_INTO_FUTURE` +/// ``TOKEN_EXPIRATION_SECONDS_INTO_FUTURE`` /// that can change the future expiration epoch time /// for a new jwt /// /// v2 this should move into the server statics: /// [`CoreConfig`](crate::core::core_config::CoreConfig) /// +/// # Returns +/// +/// ``usize`` +/// pub fn get_token_expiration_in_seconds() -> usize { @@ -233,9 +266,12 @@ pub fn get_token_expiration_in_seconds() /// create_token /// -/// create a [`TokenClaim`](crate::jwt::api::TokenClaim), and -/// sign the it using the algorithm: +/// create a +/// [`TokenClaim`](crate::jwt::api::TokenClaim) +/// and sign it using the algorithm: /// [`ES256`](jsonwebtoken::Algorithm) +/// with the jwt ``private_key`` +/// (environment variable ``TOKEN_ALGO_PRIVATE_KEY``) /// /// # Arguments /// diff --git a/src/requests/auth/create_user_token.rs b/src/requests/auth/create_user_token.rs index c960233..31db0f8 100644 --- a/src/requests/auth/create_user_token.rs +++ b/src/requests/auth/create_user_token.rs @@ -9,7 +9,7 @@ use crate::core::core_config::CoreConfig; /// create_user_token /// -/// Create an encrypted user jwt +/// Create a signed jwt for the ``user_id`` and ``user_email`` /// and store it in postgres with an expiration date /// /// # Arguments diff --git a/src/requests/auth/validate_user_token.rs b/src/requests/auth/validate_user_token.rs index e371e4e..e76b5c4 100644 --- a/src/requests/auth/validate_user_token.rs +++ b/src/requests/auth/validate_user_token.rs @@ -14,7 +14,7 @@ use crate::requests::models::user::get_user_by_id; /// validate_user_token /// -/// Confirm the token in the header token key +/// Confirm the client's jwt from the header token key /// (controlled by env var `TOKEN_HEADER=Bearer` as the default) /// is valid with the following additional restriction(s): ///