diff --git a/Cargo.toml b/Cargo.toml index 427e09d..866ad36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rtabby-web-api" -version = "0.3.0" +version = "0.4.2" edition = "2021" [features] @@ -38,4 +38,4 @@ serde = { version = "1.0.152", features = ["derive"] } serde_yaml = "0.9.16" uuid = { version = "1.6.1", features = ["serde", "v4"] } tera = { version = "1", optional = true } -reqwest = { version = "0.11", features = ["json", "rustls-tls"], default-features = false, optional = true } \ No newline at end of file +reqwest = { version = "0.12.4", features = ["json", "rustls-tls"], default-features = false, optional = true } \ No newline at end of file diff --git a/src/login/env.rs b/src/login/env.rs index 0d2900d..77676c1 100644 --- a/src/login/env.rs +++ b/src/login/env.rs @@ -1,5 +1,6 @@ pub const ENV_STATIC_FILES_BASE_DIR: &str = "STATIC_FILES_BASE_DIR"; pub const ENV_USE_HTTPS: &str = "USE_HTTPS"; +pub const ENV_HTTPS_CALLBACK: &str = "HTTPS_CALLBACK"; use crate::env as app_env; diff --git a/src/login/mod.rs b/src/login/mod.rs index 3953783..c5e1b68 100644 --- a/src/login/mod.rs +++ b/src/login/mod.rs @@ -4,10 +4,12 @@ pub mod providers; pub mod routes; pub mod services; pub mod error; -mod tools; use crate::env as app_env; +use actix_web::http::uri::Scheme; + +use log::warn; #[cfg(feature = "github-login")] use providers::github; #[cfg(feature = "gitlab-login")] @@ -21,10 +23,34 @@ use self::providers::OauthInfo; #[derive(Clone, Debug)] pub struct ProvidersConfig { + pub https_callback: bool, pub available_providers: Vec, } +impl ProvidersConfig { + + pub fn get_callback_scheme(&self) -> Scheme { + if self.https_callback { + Scheme::HTTPS + } else { + Scheme::HTTP + } + } + +} + pub fn get_provider_config() -> ProvidersConfig { + + let https_callback = if app_env::var(env::ENV_HTTPS_CALLBACK).is_ok() { + app_env::var(env::ENV_HTTPS_CALLBACK).unwrap_or(String::from("false")).to_lowercase().parse().unwrap_or(false) + } else if app_env::var(env::ENV_USE_HTTPS).is_ok() { + // DEPRECATED + warn!("\"USE_HTTPS\" deprecated. Use \"HTTPS_CALLBACK\" instead."); + app_env::var(env::ENV_USE_HTTPS).unwrap_or(String::from("0")) == "1" + } else { + false + }; + let mut available_providers: Vec = vec![]; #[cfg(feature = "github-login")] @@ -68,6 +94,7 @@ pub fn get_provider_config() -> ProvidersConfig { } ProvidersConfig { + https_callback, available_providers } } diff --git a/src/login/providers/gitlab.rs b/src/login/providers/gitlab.rs index b443dfe..d89a0d2 100644 --- a/src/login/providers/gitlab.rs +++ b/src/login/providers/gitlab.rs @@ -1,6 +1,6 @@ use crate::login::error::OauthError; use crate::login::providers::{get_user_info, get_access_token, OauthInfo, OauthUserInfo}; -use crate::login::tools; +use actix_web::http::uri::Scheme; pub mod env { pub const ENV_GITLAB_APP_CLIENT_ID: &str = "GITLAB_APP_CLIENT_ID"; @@ -13,8 +13,8 @@ pub const GITLAB_OAUTH_USER_INFO_URL: &str = "https://gitlab.com/api/v4/user"; pub type GitlabOauthUserInfo = OauthUserInfo; -pub async fn user_info(oauth: &OauthInfo, host: String, token: String) -> Result { - let redirect_uri = format!("{}://{}/login/gitlab/callback", tools::scheme(), host); +pub async fn user_info(scheme: Scheme, oauth: &OauthInfo, host: String, token: String) -> Result { + let redirect_uri = format!("{}://{}/login/gitlab/callback", scheme, host); let token = get_access_token(GITLAB_OAUTH_ACCESS_TOKEN_URL, token, oauth.client_id.clone(), oauth.client_secret.clone(), "authorization_code", Some(redirect_uri)).await?; get_user_info(GITLAB_OAUTH_USER_INFO_URL, token).await.map_err(OauthError::UserInfo)?.json::().await.map_err(OauthError::UserInfo) } diff --git a/src/login/providers/google.rs b/src/login/providers/google.rs index 809a7fe..f524557 100644 --- a/src/login/providers/google.rs +++ b/src/login/providers/google.rs @@ -1,6 +1,6 @@ use crate::login::error::OauthError; use crate::login::providers::{get_user_info, get_access_token, OauthInfo, OauthUserInfo}; -use crate::login::tools; +use actix_web::http::uri::Scheme; pub mod env { pub const ENV_GOOGLE_APP_CLIENT_ID: &str = "GOOGLE_APP_CLIENT_ID"; @@ -13,8 +13,8 @@ pub const GOOGLE_OAUTH_USER_INFO_URL: &str = "https://www.googleapis.com/oauth2/ pub type GoogleOauthUserInfo = OauthUserInfo; -pub async fn user_info(oauth: &OauthInfo, host: String, code: String) -> Result { - let redirect_uri = format!("{}://{}/login/google/callback", tools::scheme(), host); +pub async fn user_info(scheme: Scheme, oauth: &OauthInfo, host: String, code: String) -> Result { + let redirect_uri = format!("{}://{}/login/google/callback", scheme, host); let token = get_access_token(GOOGLE_OAUTH_ACCESS_TOKEN_URL, code, oauth.client_id.clone(), oauth.client_secret.clone(), "authorization_code", Some(redirect_uri)).await?; get_user_info(GOOGLE_OAUTH_USER_INFO_URL, token).await.map_err(OauthError::UserInfo)?.json::().await.map_err(OauthError::UserInfo) } diff --git a/src/login/providers/microsoft.rs b/src/login/providers/microsoft.rs index f2f708f..e1dd267 100644 --- a/src/login/providers/microsoft.rs +++ b/src/login/providers/microsoft.rs @@ -1,6 +1,6 @@ use crate::login::error::OauthError; use crate::login::providers::{get_user_info, get_access_token, OauthInfo, OauthUserInfo}; -use crate::login::tools; +use actix_web::http::uri::Scheme; use serde::Deserialize; pub mod env { @@ -29,8 +29,8 @@ impl From for OauthUserInfo { } } -pub async fn user_info(oauth: &OauthInfo, host: String, code: String) -> Result { - let redirect_uri = format!("{}://{}/login/microsoft/callback", tools::scheme(), host); +pub async fn user_info(scheme: Scheme, oauth: &OauthInfo, host: String, code: String) -> Result { + let redirect_uri = format!("{}://{}/login/microsoft/callback", scheme, host); let token = get_access_token(MICROSOFT_OAUTH_ACCESS_TOKEN_URL, code, oauth.client_id.clone(), oauth.client_secret.clone(), "authorization_code", Some(redirect_uri)).await?; get_user_info(MICROSOFT_OAUTH_USER_INFO_URL, token).await.map_err(OauthError::UserInfo)?.json::().await.map_err(OauthError::UserInfo) } diff --git a/src/login/providers/mod.rs b/src/login/providers/mod.rs index d391e62..578a22a 100644 --- a/src/login/providers/mod.rs +++ b/src/login/providers/mod.rs @@ -11,7 +11,8 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fmt; use super::error::OauthError; -use super::tools; + +use actix_web::http::uri::Scheme; #[derive(Clone, Debug)] pub struct OauthInfo { @@ -71,11 +72,11 @@ impl Provider { } } - fn get_login_url_params(&self, host: String, state: String) -> Vec<(&str, String)> { + fn get_login_url_params(&self, scheme: Scheme, host: String, state: String) -> Vec<(&str, String)> { let mut params = vec![ ("client_id", self.get_oauth_info().client_id), ("state", state), - ("redirect_uri", format!("{}://{}/login/{}/callback", tools::scheme(), host, self.name())), + ("redirect_uri", format!("{}://{}/login/{}/callback", scheme, host, self.name())), ]; #[cfg(feature = "github-login")] @@ -103,9 +104,9 @@ impl Provider { params } - pub fn get_login_url(&self, host: String, state: String) -> String { + pub fn get_login_url(&self, scheme: Scheme, host: String, state: String) -> String { - let params = self.get_login_url_params(host, state); + let params = self.get_login_url_params(scheme, host, state); let oauth_url = match self { #[cfg(feature = "github-login")] @@ -122,16 +123,16 @@ impl Provider { } #[allow(unused_variables)] - pub async fn get_user_info(&self, host: String, token: String) -> Result { + pub async fn get_user_info(&self, scheme: Scheme, host: String, token: String) -> Result { let user_info: OauthUserInfo = match self { #[cfg(feature = "github-login")] Self::Github(oauth) => github::user_info(oauth, host).await?.into(), #[cfg(feature = "gitlab-login")] - Self::Gitlab(oauth) => gitlab::user_info(oauth, host, token).await?.into(), + Self::Gitlab(oauth) => gitlab::user_info(scheme, oauth, host, token).await?.into(), #[cfg(feature = "google-login")] - Self::Google(oauth) => google::user_info(oauth, host, token).await?, + Self::Google(oauth) => google::user_info(scheme, oauth, host, token).await?, #[cfg(feature = "microsoft-login")] - Self::Microsoft(oauth) => microsoft::user_info(oauth, host, token).await?.into(), + Self::Microsoft(oauth) => microsoft::user_info(scheme, oauth, host, token).await?.into(), }; Ok(ThirdPartyUserInfo { diff --git a/src/login/routes.rs b/src/login/routes.rs index fe09455..a8fca7e 100644 --- a/src/login/routes.rs +++ b/src/login/routes.rs @@ -89,7 +89,7 @@ async fn login( let host = req.connection_info().host().to_string(); let state = Uuid::new_v4().to_string(); - let login_url = provider.get_login_url(host, state.clone()); + let login_url = provider.get_login_url(providers_config.get_callback_scheme(), host, state.clone()); let mut response = HttpResponse::TemporaryRedirect() .append_header(("Location", login_url)) @@ -148,7 +148,7 @@ async fn login_callback( let host = req.connection_info().host().to_string(); let user_info = provider - .get_user_info(host, info.code.clone()) + .get_user_info(providers_config.get_callback_scheme(), host, info.code.clone()) .await .map_err(actix_web::error::ErrorInternalServerError)?; diff --git a/src/login/tools.rs b/src/login/tools.rs deleted file mode 100644 index a1b3029..0000000 --- a/src/login/tools.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::login::env; -use crate::env as app_; - -pub fn scheme() -> String { - let scheme = if app_::var(env::ENV_USE_HTTPS).unwrap_or(String::from("0")) == "1" { - "https" - } - else { - "http" - }; - String::from(scheme) -} - diff --git a/src/main.rs b/src/main.rs index 92699a7..2ef79c1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -91,7 +91,13 @@ async fn run_app() -> Result<(), Box> { let providers_config: login::ProvidersConfig = login::get_provider_config(); #[cfg(feature = "third-party-login")] - info!("Third party login enabled: {} providers found.", providers_config.available_providers.len()); + { + info!("Third party login enabled: {} providers found.", providers_config.available_providers.len()); + if providers_config.https_callback { + info!("Third party login enabled: login callback will use HTTPS"); + } + } + let pool = storage.pool()?; let mut server = HttpServer::new(move || {