fix: some small bugs

This commit is contained in:
lewis
2026-01-30 12:18:19 +00:00
committed by Tangled
parent a9a7159d00
commit bee0bba6f4
2 changed files with 83 additions and 29 deletions
+52 -26
View File
@@ -218,7 +218,7 @@ async fn proxy_handler(
) {
let token = extracted.token;
let dpop_proof = crate::util::get_header_str(&headers, "DPoP");
let http_uri = crate::util::build_full_url(&uri.to_string());
let http_uri = crate::util::build_full_url(&format!("/xrpc{}", uri));
match crate::auth::validate_token_with_dpop(
state.user_repo.as_ref(),
@@ -243,40 +243,66 @@ async fn proxy_handler(
return e;
}
if let Some(key_bytes) = auth_user.key_bytes {
match crate::auth::create_service_token(
&auth_user.did,
&resolved.did,
method,
&key_bytes,
) {
Ok(new_token) => {
if let Ok(val) =
axum::http::HeaderValue::from_str(&format!("Bearer {}", new_token))
{
auth_header_val = Some(val);
let key_bytes = match auth_user.key_bytes {
Some(kb) => kb,
None => {
match state.user_repo.get_user_info_by_did(&auth_user.did).await {
Ok(Some(info)) => match info.key_bytes {
Some(key_bytes_enc) => {
match crate::config::decrypt_key(
&key_bytes_enc,
info.encryption_version,
) {
Ok(key) => key,
Err(e) => {
error!(error = ?e, "Failed to decrypt user key for proxy");
return ApiError::UpstreamFailure.into_response();
}
}
}
None => {
warn!(did = %auth_user.did, "User has no signing key for proxy");
return ApiError::UpstreamFailure.into_response();
}
},
Ok(None) => {
warn!(did = %auth_user.did, "User not found for proxy service auth");
return ApiError::UpstreamFailure.into_response();
}
Err(e) => {
error!(error = ?e, "DB error fetching user key for proxy");
return ApiError::UpstreamFailure.into_response();
}
}
Err(e) => {
warn!("Failed to create service token: {:?}", e);
}
};
match crate::auth::create_service_token(
&auth_user.did,
&resolved.did,
method,
&key_bytes,
) {
Ok(new_token) => {
if let Ok(val) =
axum::http::HeaderValue::from_str(&format!("Bearer {}", new_token))
{
auth_header_val = Some(val);
}
}
Err(e) => {
error!("Failed to create service token: {:?}", e);
return ApiError::UpstreamFailure.into_response();
}
}
}
Err(e) => {
info!(error = ?e, "Proxy token validation failed, returning error to client");
if matches!(
e,
crate::auth::TokenValidationError::OAuthTokenExpired
| crate::auth::TokenValidationError::TokenExpired
) {
let mut response = ApiError::from(e).into_response();
let nonce = crate::oauth::verify::generate_dpop_nonce();
if let Ok(nonce_val) = nonce.parse() {
response.headers_mut().insert("DPoP-Nonce", nonce_val);
}
return response;
let mut response = ApiError::from(e).into_response();
if let Ok(nonce_val) = crate::oauth::verify::generate_dpop_nonce().parse() {
response.headers_mut().insert("DPoP-Nonce", nonce_val);
}
return response;
}
}
}
+31 -3
View File
@@ -142,9 +142,10 @@ fn parse_query_params(query: &str) -> HashMap<String, Vec<String>> {
.split('&')
.filter_map(|part| part.split_once('='))
.fold(HashMap::new(), |mut acc, (key, value)| {
acc.entry(key.to_string())
.or_default()
.push(value.to_string());
let decoded = urlencoding::decode(value)
.map(|s| s.into_owned())
.unwrap_or_else(|_| value.to_string());
acc.entry(key.to_string()).or_default().push(decoded);
acc
})
}
@@ -480,4 +481,31 @@ mod tests {
let scope4 = parse_scope("rpc:*?aud=did:web:api.bsky.app");
assert!(matches!(scope4, ParsedScope::Rpc(_)));
}
#[test]
fn test_url_encoded_aud_with_fragment() {
let scope =
parse_scope("include:app.bsky.authFullApp?aud=did:web:api.bsky.app%23bsky_appview");
match scope {
ParsedScope::Include(i) => {
assert_eq!(i.nsid, "app.bsky.authFullApp");
assert_eq!(i.aud, Some("did:web:api.bsky.app#bsky_appview".to_string()));
}
_ => panic!("Expected Include scope"),
}
let scope2 = parse_scope(
"rpc:com.atproto.moderation.createReport?aud=did:web:api.bsky.app%23bsky_appview",
);
match scope2 {
ParsedScope::Rpc(r) => {
assert_eq!(
r.lxm,
Some("com.atproto.moderation.createReport".to_string())
);
assert_eq!(r.aud, Some("did:web:api.bsky.app#bsky_appview".to_string()));
}
_ => panic!("Expected Rpc scope"),
}
}
}