Microservice to bring 2FA to self hosted PDSes
0

Configure Feed

Select the types of activity you want to include in your feed.

Bugfix for 2fa on curl

+42 -68
+2 -2
justfile
··· 2 2 docker buildx build \ 3 3 --platform linux/arm64,linux/amd64 \ 4 4 --tag fatfingers23/pds_gatekeeper:latest \ 5 - --tag fatfingers23/pds_gatekeeper:0.1.0.5 \ 6 - --push . 5 + --tag fatfingers23/pds_gatekeeper:0.1.0.7 \ 6 + --push .
+36
src/helpers.rs
··· 89 89 } 90 90 } 91 91 92 + /// Forward an incoming request to the PDS as a POST, filtering out hop-by-hop headers. 93 + pub async fn proxy_post( 94 + state: &AppState, 95 + headers: &HeaderMap, 96 + path: &str, 97 + body_bytes: Vec<u8>, 98 + ) -> Result<Response<Body>, StatusCode> { 99 + let uri = format!("{}{}", state.app_config.pds_base_url, path); 100 + 101 + let mut req = axum::http::Request::post(uri); 102 + if let Some(req_headers) = req.headers_mut() { 103 + for (name, value) in headers.iter() { 104 + let skip = matches!( 105 + name.as_str(), 106 + "host" | "content-length" | "transfer-encoding" | "connection" 107 + ); 108 + if !skip { 109 + req_headers.append(name.clone(), value.clone()); 110 + } 111 + } 112 + } 113 + 114 + let req = req 115 + .body(Body::from(body_bytes)) 116 + .map_err(|_| StatusCode::BAD_REQUEST)?; 117 + 118 + let proxied = state 119 + .reverse_proxy_client 120 + .request(req) 121 + .await 122 + .map_err(|_| StatusCode::BAD_REQUEST)? 123 + .into_response(); 124 + 125 + Ok(proxied) 126 + } 127 + 92 128 /// Build a JSON error response with the required Content-Type header 93 129 /// Content-Type: application/json;charset=utf-8 94 130 /// Body shape: { "error": string, "message": string }
+4 -66
src/xrpc/com_atproto_server.rs
··· 1 1 use crate::AppState; 2 2 use crate::helpers::{ 3 3 AuthResult, ProxiedResult, TokenCheckError, VerifyServiceAuthError, json_error_response, 4 - preauth_check, proxy_get_json, verify_gate_token, verify_service_auth, 4 + preauth_check, proxy_get_json, proxy_post, verify_gate_token, verify_service_auth, 5 5 }; 6 6 use crate::middleware::Did; 7 7 use axum::body::{Body, to_bytes}; ··· 142 142 } 143 143 AuthResult::ProxyThrough => { 144 144 //No 2FA or already passed 145 - let uri = format!( 146 - "{}{}", 147 - state.app_config.pds_base_url, "/xrpc/com.atproto.server.createSession" 148 - ); 149 - 150 - let mut req = axum::http::Request::post(uri); 151 - if let Some(req_headers) = req.headers_mut() { 152 - req_headers.extend(headers.clone()); 153 - } 154 - 155 145 let payload_bytes = 156 146 serde_json::to_vec(&payload).map_err(|_| StatusCode::BAD_REQUEST)?; 157 - let req = req 158 - .body(Body::from(payload_bytes)) 159 - .map_err(|_| StatusCode::BAD_REQUEST)?; 160 - 161 - let proxied = state 162 - .reverse_proxy_client 163 - .request(req) 164 - .await 165 - .map_err(|_| StatusCode::BAD_REQUEST)? 166 - .into_response(); 167 - 168 - Ok(proxied) 147 + proxy_post(&state, &headers, "/xrpc/com.atproto.server.createSession", payload_bytes).await 169 148 } 170 149 AuthResult::TokenCheckFailed(err) => match err { 171 150 TokenCheckError::InvalidToken => { ··· 285 264 } 286 265 } 287 266 // Updating the actual email address by sending it on to the PDS 288 - let uri = format!( 289 - "{}{}", 290 - state.app_config.pds_base_url, "/xrpc/com.atproto.server.updateEmail" 291 - ); 292 - let mut req = axum::http::Request::post(uri); 293 - if let Some(req_headers) = req.headers_mut() { 294 - req_headers.extend(headers.clone()); 295 - } 296 - 297 267 let payload_bytes = serde_json::to_vec(&payload).map_err(|_| StatusCode::BAD_REQUEST)?; 298 - let req = req 299 - .body(Body::from(payload_bytes)) 300 - .map_err(|_| StatusCode::BAD_REQUEST)?; 301 - 302 - let proxied = state 303 - .reverse_proxy_client 304 - .request(req) 305 - .await 306 - .map_err(|_| StatusCode::BAD_REQUEST)? 307 - .into_response(); 308 - 309 - Ok(proxied) 268 + proxy_post(&state, &headers, "/xrpc/com.atproto.server.updateEmail", payload_bytes).await 310 269 } 311 270 312 271 pub async fn get_session( ··· 581 540 } 582 541 583 542 // Rebuild the request with the same body and headers 584 - let uri = format!( 585 - "{}{}", 586 - state.app_config.pds_base_url, "/xrpc/com.atproto.server.createAccount" 587 - ); 588 - 589 - let mut new_req = axum::http::Request::post(&uri); 590 - if let Some(req_headers) = new_req.headers_mut() { 591 - *req_headers = headers; 592 - } 593 - 594 - let new_req = new_req 595 - .body(Body::from(body_bytes)) 596 - .map_err(|_| StatusCode::BAD_REQUEST)?; 597 - 598 - let proxied = state 599 - .reverse_proxy_client 600 - .request(new_req) 601 - .await 602 - .map_err(|_| StatusCode::BAD_REQUEST)? 603 - .into_response(); 604 - 605 - Ok(proxied) 543 + proxy_post(&state, &headers, "/xrpc/com.atproto.server.createAccount", body_bytes.to_vec()).await 606 544 }