diff --git a/libs/app_error/src/lib.rs b/libs/app_error/src/lib.rs index 23af6578..214a9c8b 100644 --- a/libs/app_error/src/lib.rs +++ b/libs/app_error/src/lib.rs @@ -212,7 +212,7 @@ impl From for AppError { (400, m) if m.starts_with("User already registered") => { AppError::UserAlreadyRegistered(err.msg) }, - (401, _) => AppError::UserUnAuthorized(err.msg), + (401, _) => AppError::UserUnAuthorized(format!("{}:{}", err.code, err.msg)), (422, _) => AppError::InvalidRequest(err.msg), _ => AppError::OAuthError(err.to_string()), }, diff --git a/libs/client-api/src/http.rs b/libs/client-api/src/http.rs index 296d9e12..024cc335 100644 --- a/libs/client-api/src/http.rs +++ b/libs/client-api/src/http.rs @@ -40,7 +40,7 @@ use shared_entity::response::{AppResponse, AppResponseError}; use std::sync::atomic::AtomicBool; use std::sync::Arc; use std::time::Duration; -use tracing::{event, instrument, trace, warn}; +use tracing::{error, event, instrument, trace, warn}; use url::Url; use gotrue_entity::dto::SignUpResponse::{Authenticated, NotAuthenticated}; @@ -215,8 +215,11 @@ impl Client { })?; let access_token = access_token.ok_or(url_missing_param("access_token"))?; - let (user, new) = self.verify_token(&access_token).await?; + if access_token.is_empty() { + return Err(AppError::OAuthError("Empty access token".to_string()).into()); + } + let (user, new) = self.verify_token(&access_token).await?; self.token.write().set(GotrueTokenResponse { access_token, token_type: token_type.ok_or(url_missing_param("token_type"))?, @@ -336,6 +339,7 @@ impl Client { } #[inline] + #[instrument(level = "debug", skip_all, err)] async fn verify_token(&self, access_token: &str) -> Result<(User, bool), AppResponseError> { let user = self.gotrue_client.user_info(access_token).await?; let is_new = self.verify_token_cloud(access_token).await?; @@ -451,15 +455,20 @@ impl Client { pub fn access_token(&self) -> Result { match &self.token.try_read_for(Duration::from_secs(2)) { None => Err(AppError::Unhandled("Failed to read token".to_string()).into()), - Some(token) => Ok( - token + Some(token) => { + let access_token = token .as_ref() .ok_or(AppResponseError::from(AppError::NotLoggedIn( "fail to get access token. Token is empty".to_string(), )))? .access_token - .clone(), - ), + .clone(); + + if access_token.is_empty() { + error!("Unexpected empty access token"); + } + Ok(access_token) + }, } } diff --git a/libs/gotrue/src/api.rs b/libs/gotrue/src/api.rs index 0f8075e2..8df34e39 100644 --- a/libs/gotrue/src/api.rs +++ b/libs/gotrue/src/api.rs @@ -11,6 +11,7 @@ use gotrue_entity::dto::{ use gotrue_entity::error::{GoTrueError, GoTrueErrorSerde, GotrueClientError}; use gotrue_entity::sso::{SSOProvider, SSOProviders}; use infra::reqwest::{check_response, from_body, from_response}; +use reqwest::{Method, RequestBuilder}; #[derive(Clone)] pub struct Client { @@ -97,10 +98,9 @@ impl Client { #[tracing::instrument(skip_all, err)] pub async fn logout(&self, access_token: &str) -> Result<(), GoTrueError> { + let url = format!("{}/logout", self.base_url); let resp = self - .client - .post(format!("{}/logout", self.base_url)) - .header("Authorization", format!("Bearer {}", access_token)) + .http_client_with_auth(Method::POST, &url, access_token) .send() .await?; Ok(check_response(resp).await?) @@ -110,9 +110,7 @@ impl Client { pub async fn user_info(&self, access_token: &str) -> Result { let url = format!("{}/user", self.base_url); let resp = self - .client - .get(&url) - .header("Authorization", format!("Bearer {}", access_token)) + .http_client_with_auth(Method::GET, &url, access_token) .send() .await?; to_gotrue_result(resp).await @@ -123,10 +121,9 @@ impl Client { access_token: &str, update_user_params: &UpdateGotrueUserParams, ) -> Result { + let url = format!("{}/user", self.base_url); let resp = self - .client - .put(format!("{}/user", self.base_url)) - .header("Authorization", format!("Bearer {}", access_token)) + .http_client_with_auth(Method::PUT, &url, access_token) .json(update_user_params) .send() .await?; @@ -138,10 +135,9 @@ impl Client { &self, access_token: &str, ) -> Result { + let url = format!("{}/admin/users", self.base_url); let resp = self - .client - .get(format!("{}/admin/users", self.base_url)) - .header("Authorization", format!("Bearer {}", access_token)) + .http_client_with_auth(Method::GET, &url, access_token) .send() .await?; to_gotrue_result(resp).await @@ -152,10 +148,9 @@ impl Client { access_token: &str, user_id: &str, // uuid ) -> Result { + let url = format!("{}/admin/users/{}", self.base_url, user_id); let resp = self - .client - .get(format!("{}/admin/users/{}", self.base_url, user_id)) - .header("Authorization", format!("Bearer {}", access_token)) + .http_client_with_auth(Method::GET, &url, access_token) .send() .await?; to_gotrue_result(resp).await @@ -167,10 +162,9 @@ impl Client { user_uuid: &str, delete_user_params: &AdminDeleteUserParams, ) -> Result<(), GoTrueError> { + let url = format!("{}/admin/users/{}", self.base_url, user_uuid); let resp = self - .client - .delete(format!("{}/admin/users/{}", self.base_url, user_uuid)) - .header("Authorization", format!("Bearer {}", access_token)) + .http_client_with_auth(Method::DELETE, &url, access_token) .json(&delete_user_params) .send() .await?; @@ -183,10 +177,9 @@ impl Client { user_uuid: &str, admin_user_params: &AdminUserParams, ) -> Result { + let url = format!("{}/admin/users/{}", self.base_url, user_uuid); let resp = self - .client - .put(format!("{}/admin/users/{}", self.base_url, user_uuid)) - .header("Authorization", format!("Bearer {}", access_token)) + .http_client_with_auth(Method::PUT, &url, access_token) .json(&admin_user_params) .send() .await?; @@ -198,10 +191,9 @@ impl Client { access_token: &str, admin_user_params: &AdminUserParams, ) -> Result { + let url = format!("{}/admin/users", self.base_url); let resp = self - .client - .post(format!("{}/admin/users", self.base_url)) - .header("Authorization", format!("Bearer {}", access_token)) + .http_client_with_auth(Method::POST, &url, access_token) .json(&admin_user_params) .send() .await?; @@ -213,10 +205,9 @@ impl Client { access_token: &str, generate_link_params: &GenerateLinkParams, ) -> Result { + let url = format!("{}/admin/generate_link", self.base_url); let resp = self - .client - .post(format!("{}/admin/generate_link", self.base_url)) - .header("Authorization", format!("Bearer {}", access_token)) + .http_client_with_auth(Method::POST, &url, access_token) .json(&generate_link_params) .send() .await?; @@ -228,10 +219,9 @@ impl Client { access_token: &str, magic_link_params: &MagicLinkParams, ) -> Result<(), GoTrueError> { + let url = format!("{}/magiclink", self.base_url); let resp = self - .client - .post(format!("{}/magiclink", self.base_url)) - .header("Authorization", format!("Bearer {}", access_token)) + .http_client_with_auth(Method::POST, &url, access_token) .json(&magic_link_params) .send() .await?; @@ -242,10 +232,9 @@ impl Client { &self, access_token: &str, ) -> Result { + let url = format!("{}/admin/sso/providers", self.base_url); let resp = self - .client - .get(format!("{}/admin/sso/providers", self.base_url)) - .header("Authorization", format!("Bearer {}", access_token)) + .http_client_with_auth(Method::GET, &url, access_token) .send() .await?; to_gotrue_result(resp).await @@ -256,10 +245,9 @@ impl Client { access_token: &str, create_sso_provider_params: &CreateSSOProviderParams, ) -> Result { + let url = format!("{}/admin/sso/providers", self.base_url); let resp = self - .client - .post(format!("{}/admin/sso/providers", self.base_url)) - .header("Authorization", format!("Bearer {}", access_token)) + .http_client_with_auth(Method::POST, &url, access_token) .json(create_sso_provider_params) .send() .await?; @@ -271,10 +259,9 @@ impl Client { access_token: &str, idp_id: &str, ) -> Result { + let url = format!("{}/admin/sso/providers/{}", self.base_url, idp_id); let resp = self - .client - .get(format!("{}/admin/sso/providers/{}", self.base_url, idp_id)) - .header("Authorization", format!("Bearer {}", access_token)) + .http_client_with_auth(Method::GET, &url, access_token) .send() .await?; to_gotrue_result(resp).await @@ -286,10 +273,9 @@ impl Client { idp_id: &str, create_sso_provider_params: &CreateSSOProviderParams, ) -> Result { + let url = format!("{}/admin/sso/providers/{}", self.base_url, idp_id); let resp = self - .client - .put(format!("{}/admin/sso/providers/{}", self.base_url, idp_id)) - .header("Authorization", format!("Bearer {}", access_token)) + .http_client_with_auth(Method::PUT, &url, access_token) .json(create_sso_provider_params) .send() .await?; @@ -301,14 +287,22 @@ impl Client { access_token: &str, idp_id: &str, ) -> Result { + let url = format!("{}/admin/sso/providers/{}", self.base_url, idp_id); let resp = self - .client - .delete(format!("{}/admin/sso/providers/{}", self.base_url, idp_id)) - .header("Authorization", format!("Bearer {}", access_token)) + .http_client_with_auth(Method::DELETE, &url, access_token) .send() .await?; to_gotrue_result(resp).await } + + pub fn http_client_with_auth( + &self, + method: Method, + url: &str, + access_token: &str, + ) -> RequestBuilder { + self.client.request(method, url).bearer_auth(access_token) + } } async fn to_gotrue_result(resp: reqwest::Response) -> Result