slack status without the slack status.zzstoatzz.io/
quickslice

Add auth domain workaround for same-site OAuth issue

- Add APP_URL config for main app domain
- Redirect login from status domain to auth domain
- After OAuth success, redirect back to status domain
- Use config values instead of hardcoding URLs

This works around the PDS rejecting same-site OAuth requests by using auth.zzstoatzz.com for OAuth flow while keeping status.zzstoatzz.io as the main app.

+38 -6
+32 -5
src/api/auth.rs
··· 64 64 request: HttpRequest, 65 65 params: web::Query<OAuthCallbackParams>, 66 66 oauth_client: web::Data<OAuthClientType>, 67 + config: web::Data<config::Config>, 67 68 session: Session, 68 69 ) -> HttpResponse { 69 70 // Check if there's an OAuth error from BlueSky ··· 109 110 match agent.did().await { 110 111 Some(did) => { 111 112 session.insert("did", did).unwrap(); 112 - Redirect::to("/") 113 + // Redirect back to main app domain after successful auth 114 + let redirect_to = if config.oauth_redirect_base != config.app_url { 115 + config.app_url.clone() 116 + } else { 117 + "/".to_string() 118 + }; 119 + Redirect::to(redirect_to) 113 120 .see_other() 114 121 .respond_to(&request) 115 122 .map_into_boxed_body() ··· 136 143 137 144 /// Takes you to the login page 138 145 #[get("/login")] 139 - pub async fn login() -> Result<impl Responder> { 146 + pub async fn login( 147 + request: HttpRequest, 148 + config: web::Data<config::Config>, 149 + ) -> Result<HttpResponse> { 150 + // Check if we're on the main app domain and redirect to auth domain 151 + if let Some(host) = request.headers().get("host") { 152 + if let Ok(host_str) = host.to_str() { 153 + // Extract just the host from the app_url 154 + if let Ok(app_url) = url::Url::parse(&config.app_url) { 155 + if let Some(app_host) = app_url.host_str() { 156 + if host_str.starts_with(app_host) 157 + && config.oauth_redirect_base != config.app_url 158 + { 159 + let redirect_url = format!("{}/login", config.oauth_redirect_base); 160 + return Ok(HttpResponse::Found() 161 + .append_header(("Location", redirect_url)) 162 + .finish()); 163 + } 164 + } 165 + } 166 + } 167 + } 168 + 140 169 let html = LoginTemplate { 141 170 title: "Log in", 142 171 error: None, 143 172 }; 144 - Ok(web::Html::new( 145 - html.render().expect("template should be valid"), 146 - )) 173 + Ok(HttpResponse::Ok().body(html.render().expect("template should be valid"))) 147 174 } 148 175 149 176 /// Logs you out by destroying your cookie on the server and web browser
+5 -1
src/config.rs
··· 14 14 /// Database URL (defaults to local SQLite) 15 15 pub database_url: String, 16 16 17 - /// OAuth redirect base URL 17 + /// OAuth redirect base URL (auth domain) 18 18 pub oauth_redirect_base: String, 19 + 20 + /// Main app URL (status domain) 21 + pub app_url: String, 19 22 20 23 /// Server host 21 24 pub server_host: String, ··· 49 52 .unwrap_or_else(|_| "sqlite://./statusphere.sqlite3".to_string()), 50 53 oauth_redirect_base: env::var("OAUTH_REDIRECT_BASE") 51 54 .unwrap_or_else(|_| "http://localhost:8080".to_string()), 55 + app_url: env::var("APP_URL").unwrap_or_else(|_| "http://localhost:8080".to_string()), 52 56 server_host: env::var("SERVER_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()), 53 57 server_port: env::var("SERVER_PORT") 54 58 .unwrap_or_else(|_| "8080".to_string())
+1
templates/login.html
··· 424 424 if (themeToggle) { 425 425 themeToggle.addEventListener('click', toggleTheme); 426 426 } 427 + 427 428 }); 428 429 </script> 429 430 {%endblock content%}