diff --git a/Cargo.lock b/Cargo.lock index 6cb77627a..32ffc03f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -395,7 +395,6 @@ dependencies = [ "reqwest 0.11.27", "serde", "serde_json", - "serde_urlencoded", "sha2", "shared-entity", "tokio", diff --git a/admin_frontend/Cargo.toml b/admin_frontend/Cargo.toml index ac305e7b4..e88429546 100644 --- a/admin_frontend/Cargo.toml +++ b/admin_frontend/Cargo.toml @@ -34,4 +34,3 @@ rand = "0.8.5" sha2 = "0.10.8" base64 = "0.22.1" urlencoding = "2.1.3" -serde_urlencoded = "0.7.1" diff --git a/admin_frontend/src/models.rs b/admin_frontend/src/models.rs index 6d6fddf12..b478469f9 100644 --- a/admin_frontend/src/models.rs +++ b/admin_frontend/src/models.rs @@ -44,6 +44,8 @@ pub struct WebAppOAuthLoginRequest { // Use actions (with params) after login pub action: Option, + + // Workspace Invitation pub workspace_invitation_id: Option, pub workspace_name: Option, pub workspace_icon: Option, @@ -51,7 +53,8 @@ pub struct WebAppOAuthLoginRequest { pub user_icon: Option, pub workspace_member_count: Option, - // pub redirect + // Redirect + pub redirect_to: Option, // Errors pub error: Option, diff --git a/admin_frontend/src/session.rs b/admin_frontend/src/session.rs index 7055745e6..4b0e6baca 100644 --- a/admin_frontend/src/session.rs +++ b/admin_frontend/src/session.rs @@ -1,12 +1,9 @@ -use std::{ - collections::HashMap, - time::{SystemTime, UNIX_EPOCH}, -}; +use std::time::{SystemTime, UNIX_EPOCH}; use axum::{ async_trait, extract::{FromRequestParts, OriginalUri}, - http::{header, request::Parts, HeaderMap, StatusCode}, + http::request::Parts, response::{IntoResponse, Redirect}, }; use axum_extra::extract::{cookie::Cookie, CookieJar}; @@ -16,7 +13,7 @@ use jwt::{Claims, Header}; use redis::{aio::ConnectionManager, AsyncCommands, FromRedisValue, ToRedisArgs}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; -use crate::{ext::api::verify_token_cloud, AppState}; +use crate::AppState; static SESSION_EXPIRATION: usize = 60 * 60 * 24; // 1 day @@ -159,60 +156,6 @@ impl FromRequestParts for UserSession { .get::() .map(|uri| urlencoding::encode(&uri.to_string()).to_string()); - // attempt to redirect after setting new session - if let Some(p) = parts.uri.query() { - match serde_urlencoded::from_str::>(p) { - Ok(params) => { - if let Some(refresh_token) = params.get("refresh_token") { - match state - .gotrue_client - .token(&gotrue::grant::Grant::RefreshToken( - gotrue::grant::RefreshTokenGrant { - refresh_token: refresh_token.to_string(), - }, - )) - .await - { - Ok(token) => { - match verify_token_cloud( - token.access_token.as_str(), - state.appflowy_cloud_url.as_str(), - ) - .await - { - Ok(()) => { - let new_session_id = uuid::Uuid::new_v4(); - let new_session = UserSession { - session_id: new_session_id.to_string(), - token, - }; - state - .session_store - .put_user_session(&new_session) - .await - .unwrap(); - - let session_cookie = jar.add(new_session_cookie(new_session_id)); - - if let Some(original_url) = original_url { - let mut headers = HeaderMap::new(); - headers.insert(header::LOCATION, original_url.parse().unwrap()); - return Err((StatusCode::SEE_OTHER, headers, session_cookie).into_response()); - } - }, - Err(err) => { - tracing::warn!("failed to verify token: {}", format!("{:?}", err)) - }, - } - }, - Err(err) => tracing::error!("failed to refresh token: {}", err), - }; - } - }, - Err(err) => tracing::error!("failed to parse query params: {}", err), - } - } - match original_url { Some(url) => Err(Redirect::to(&format!("/web/login?redirect_to={}", url)).into_response()), None => Err(Redirect::to("/web/login").into_response()), diff --git a/admin_frontend/src/templates.rs b/admin_frontend/src/templates.rs index a720e27d4..d1970d558 100644 --- a/admin_frontend/src/templates.rs +++ b/admin_frontend/src/templates.rs @@ -62,6 +62,7 @@ pub struct ChangePassword; pub struct Login<'a> { pub oauth_providers: &'a [&'a str], pub redirect_to: Option<&'a str>, + pub oauth_redirect_to: Option<&'a str>, } #[derive(Template)] diff --git a/admin_frontend/src/web_api.rs b/admin_frontend/src/web_api.rs index ff94f1873..cc00482d5 100644 --- a/admin_frontend/src/web_api.rs +++ b/admin_frontend/src/web_api.rs @@ -580,15 +580,13 @@ async fn session_login( }; state.session_store.put_user_session(&new_session).await?; - let decoded_redirect_to = redirect_to - .map(|s| match urlencoding::decode(s) { - Ok(r) => Some(r), - Err(err) => { - tracing::error!("failed to decode redirect_to: {}", err); - None - }, - }) - .flatten(); + let decoded_redirect_to = redirect_to.and_then(|s| match urlencoding::decode(s) { + Ok(r) => Some(r), + Err(err) => { + tracing::error!("failed to decode redirect_to: {}", err); + None + }, + }); Ok( ( diff --git a/admin_frontend/src/web_app.rs b/admin_frontend/src/web_app.rs index 0b56811f5..d61834ae3 100644 --- a/admin_frontend/src/web_app.rs +++ b/admin_frontend/src/web_app.rs @@ -177,10 +177,22 @@ async fn login_callback_query_handler( return Ok(redirect_html.into_response()); }; let open_or_dl_html = render_template(templates::OpenAppFlowyOrDownload {})?; - return Ok((jar, open_or_dl_html).into_response()); + Ok((jar, open_or_dl_html).into_response()) }, }, - None => home_handler(State(state), new_session, jar).await, + None => match query.redirect_to { + Some(redirect_url) => match urlencoding::decode(&redirect_url).map(String::from) { + Ok(redirect_url) => { + let redirect_html = render_template(templates::Redirect { redirect_url })?; + Ok((jar, redirect_html).into_response()) + }, + Err(err) => { + tracing::error!("Error decoding redirect_url: {:?}", err); + home_handler(State(state), new_session, jar).await + }, + }, + None => home_handler(State(state), new_session, jar).await, + }, } } @@ -351,13 +363,22 @@ async fn login_handler( ) -> Result, WebAppError> { let redirect_to = login .redirect_to - .map(|r| urlencoding::encode(&r).to_string()); + .as_ref() + .map(|r| urlencoding::encode(r).to_string()); + let oauth_redirect_to = login.redirect_to.as_ref().map(|r| { + urlencoding::encode(&format!( + "/web/login-callback?redirect_to={}", + urlencoding::encode(r) + )) + .to_string() + }); let external = state.gotrue_client.settings().await?.external; let oauth_providers = external.oauth_providers(); render_template(templates::Login { oauth_providers: &oauth_providers, redirect_to: redirect_to.as_deref(), + oauth_redirect_to: oauth_redirect_to.as_deref(), }) } diff --git a/admin_frontend/templates/pages/login.html b/admin_frontend/templates/pages/login.html index 696be9a3c..6b512d1e1 100644 --- a/admin_frontend/templates/pages/login.html +++ b/admin_frontend/templates/pages/login.html @@ -96,7 +96,7 @@

OAuth Login

{% for provider in oauth_providers %}