diff --git a/admin_frontend/src/web_api.rs b/admin_frontend/src/web_api.rs index 9b5b45a5..4fe9a14e 100644 --- a/admin_frontend/src/web_api.rs +++ b/admin_frontend/src/web_api.rs @@ -7,7 +7,7 @@ use crate::response::WebApiResponse; use crate::session::{self, UserSession}; use crate::{models::WebApiLoginRequest, AppState}; use axum::extract::Path; -use axum::http::{status, HeaderMap, HeaderValue}; +use axum::http::{status, HeaderMap}; use axum::response::Result; use axum::routing::delete; use axum::Form; @@ -99,22 +99,13 @@ pub async fn change_password_handler( Ok(WebApiResponse::<()>::from_str("Password changed".into())) } -static DEFAULT_HOST: HeaderValue = HeaderValue::from_static("localhost"); -static DEFAULT_SCHEME: HeaderValue = HeaderValue::from_static("http"); pub async fn post_oauth_login_handler( header_map: HeaderMap, Path(provider): Path, ) -> Result, WebApiError<'static>> { - let host = header_map - .get("host") - .unwrap_or(&DEFAULT_HOST) - .to_str() - .unwrap(); - let scheme = header_map - .get("x-scheme") - .unwrap_or(&DEFAULT_SCHEME) - .to_str() - .unwrap(); + let scheme = get_header_value_or_default(&header_map, "x-scheme", "http"); + let host = get_header_value_or_default(&header_map, "host", "localhost"); + let base_url = format!("{}://{}", scheme, host); let redirect_uri = format!("{}/web/oauth_login_redirect", base_url); @@ -125,6 +116,23 @@ pub async fn post_oauth_login_handler( Ok(oauth_url.into()) } +fn get_header_value_or_default<'a>( + header_map: &'a HeaderMap, + header_name: &str, + default: &'a str, +) -> &'a str { + match header_map.get(header_name) { + Some(v) => match v.to_str() { + Ok(v) => v, + Err(e) => { + tracing::error!("failed to get header value {}: {}, {:?}", header_name, e, v); + default + }, + }, + None => default, + } +} + pub async fn admin_update_user_handler( State(state): State, session: UserSession, @@ -226,6 +234,7 @@ pub async fn login_refresh_handler( // sign up if not exist pub async fn login_handler( State(state): State, + header_map: HeaderMap, jar: CookieJar, Form(param): Form, ) -> Result<(CookieJar, HeaderMap, WebApiResponse<()>), WebApiError<'static>> { @@ -252,7 +261,15 @@ pub async fn login_handler( ("invalid_grant", Some("Invalid login credentials")) => { let sign_up_res = state .gotrue_client - .sign_up(¶m.email, ¶m.password) + .sign_up_with_referrer( + ¶m.email, + ¶m.password, + Some(get_header_value_or_default( + &header_map, + "host", + "localhost", + )), + ) .await; match sign_up_res { diff --git a/libs/gotrue/src/api.rs b/libs/gotrue/src/api.rs index 9ad0d276..7671cb09 100644 --- a/libs/gotrue/src/api.rs +++ b/libs/gotrue/src/api.rs @@ -52,12 +52,28 @@ impl Client { #[tracing::instrument(skip_all, err)] pub async fn sign_up(&self, email: &str, password: &str) -> Result { + self.sign_up_with_referrer(email, password, None).await + } + + #[tracing::instrument(skip_all, err)] + pub async fn sign_up_with_referrer( + &self, + email: &str, + password: &str, + redirect_to: Option<&str>, + ) -> Result { let payload = serde_json::json!({ "email": email, "password": password, }); let url: String = format!("{}/signup", self.base_url); - let resp = self.client.post(&url).json(&payload).send().await?; + + let mut req_builder = self.client.post(&url).json(&payload); + if let Some(redirect_to) = redirect_to { + req_builder = req_builder.header("redirect_to", redirect_to); + } + + let resp = req_builder.send().await?; to_gotrue_result(resp).await } diff --git a/nginx/nginx.conf b/nginx/nginx.conf index 284a959f..62ae2ffb 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -37,6 +37,7 @@ http { # Allow headers like redirect_to to be handed over to the gotrue # for correct redirecting + proxy_set_header Host $http_host; proxy_pass_request_headers on; } @@ -59,29 +60,29 @@ http { # Minio Web UI # Derive from: https://min.io/docs/minio/linux/integrations/setup-nginx-proxy-with-minio.html location /minio/ { - rewrite ^/minio/(.*) /$1 break; - proxy_set_header Host $http_host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-NginX-Proxy true; + rewrite ^/minio/(.*) /$1 break; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-NginX-Proxy true; - ## This is necessary to pass the correct IP to be hashed - real_ip_header X-Real-IP; + ## This is necessary to pass the correct IP to be hashed + real_ip_header X-Real-IP; - proxy_connect_timeout 300; + proxy_connect_timeout 300; - ## To support websockets in MinIO versions released after January 2023 - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - # Some environments may encounter CORS errors (Kubernetes + Nginx Ingress) - # Uncomment the following line to set the Origin request to an empty string - # proxy_set_header Origin ''; + ## To support websockets in MinIO versions released after January 2023 + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + # Some environments may encounter CORS errors (Kubernetes + Nginx Ingress) + # Uncomment the following line to set the Origin request to an empty string + # proxy_set_header Origin ''; - chunked_transfer_encoding off; + chunked_transfer_encoding off; - proxy_pass http://minio:9001; + proxy_pass http://minio:9001; } # PgAdmin