Skip to content

Commit d53bd5e

Browse files
test(auth): add Privy middleware integration tests (#839)
1 parent 3fc4e60 commit d53bd5e

1 file changed

Lines changed: 105 additions & 2 deletions

File tree

backend/tests/privy_auth_tests.rs

Lines changed: 105 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
/// signature/audience/issuer verification rather than a placeholder.
44
use axum::{
55
body::Body,
6+
extract::Extension,
67
http::{Request, StatusCode},
8+
routing::get,
79
Router,
810
};
911
use chrono::Utc;
@@ -201,7 +203,24 @@ fn create_test_app(pool: PgPool) -> Router {
201203
privy: Arc::new(PrivyJwksClient::new(mock_jwks_url().to_string())),
202204
privy_app_id: TEST_APP_ID.to_string(),
203205
};
204-
Router::new().nest("/api/auth", zaps_backend::api::auth_routes_with_state(state))
206+
Router::new().nest(
207+
"/api/auth",
208+
zaps_backend::api::auth_routes_with_state(state),
209+
)
210+
}
211+
212+
async fn protected_identity(
213+
Extension(user): Extension<zaps_backend::api::AuthenticatedUser>,
214+
) -> String {
215+
user.address
216+
}
217+
218+
fn create_protected_test_app(pool: PgPool) -> Router {
219+
zaps_backend::api::protected_routes(
220+
Router::new().route("/protected", get(protected_identity)),
221+
pool,
222+
zaps_backend::api::AuthTokenCache::new(),
223+
)
205224
}
206225

207226
#[cfg(test)]
@@ -246,7 +265,10 @@ mod privy_auth_integration_tests {
246265
let body = response.into_body().collect().await.unwrap().to_bytes();
247266
let json: Value = serde_json::from_slice(&body).unwrap();
248267

249-
assert!(json["token"].is_string(), "Response should contain JWT token");
268+
assert!(
269+
json["token"].is_string(),
270+
"Response should contain JWT token"
271+
);
250272
assert_eq!(json["username"].as_str().unwrap(), "u_GBPK7THXDEPNBQB5K");
251273
assert_eq!(json["privy_did"].as_str().unwrap(), privy_did);
252274

@@ -739,4 +761,85 @@ mod privy_auth_integration_tests {
739761
"Token issued for a different Privy app must be rejected"
740762
);
741763
}
764+
765+
/// Test 12 - A valid Privy token produces a session token that passes the
766+
/// protected-route authentication middleware.
767+
#[tokio::test]
768+
async fn test_valid_privy_token_passes_auth_middleware() {
769+
let pool = setup_test_pool().await;
770+
let stellar_addr = "GBPK7THXDEPNBQB5K3EMQL5FZAQLHJ4XPBWJFNV3EPJN7CVPQGJZ6PBN";
771+
let privy_did = format!("did:privy:test_{}", Uuid::new_v4());
772+
cleanup_test_user(&pool, stellar_addr).await;
773+
774+
let request = Request::builder()
775+
.method("POST")
776+
.uri("/api/auth/privy")
777+
.header("content-type", "application/json")
778+
.body(Body::from(
779+
json!({
780+
"privy_token": create_mock_privy_token(&privy_did, Some(stellar_addr), false),
781+
"privy_did": privy_did,
782+
"stellar_address": stellar_addr
783+
})
784+
.to_string(),
785+
))
786+
.unwrap();
787+
788+
let response = create_test_app(pool.clone())
789+
.oneshot(request)
790+
.await
791+
.unwrap();
792+
assert_eq!(response.status(), StatusCode::CREATED);
793+
let body = response.into_body().collect().await.unwrap().to_bytes();
794+
let auth_response: Value = serde_json::from_slice(&body).unwrap();
795+
let session_token = auth_response["token"].as_str().unwrap();
796+
797+
let protected_request = Request::builder()
798+
.uri("/protected")
799+
.header("authorization", format!("Bearer {session_token}"))
800+
.body(Body::empty())
801+
.unwrap();
802+
let protected_response = create_protected_test_app(pool.clone())
803+
.oneshot(protected_request)
804+
.await
805+
.unwrap();
806+
807+
assert_eq!(protected_response.status(), StatusCode::OK);
808+
let body = protected_response
809+
.into_body()
810+
.collect()
811+
.await
812+
.unwrap()
813+
.to_bytes();
814+
assert_eq!(body, stellar_addr);
815+
816+
cleanup_test_user(&pool, stellar_addr).await;
817+
}
818+
819+
/// Test 13 - An invalid Privy verification response must not produce a
820+
/// session token and is returned as 401 Unauthorized.
821+
#[tokio::test]
822+
async fn test_invalid_privy_token_returns_unauthorized() {
823+
let pool = setup_test_pool().await;
824+
let stellar_addr = "GBPK7THXDEPNBQB5K3EMQL5FZAQLHJ4XPBWJFNV3EPJN7CVPQGJZ6PBN";
825+
let privy_did = format!("did:privy:test_{}", Uuid::new_v4());
826+
827+
let request = Request::builder()
828+
.method("POST")
829+
.uri("/api/auth/privy")
830+
.header("content-type", "application/json")
831+
.body(Body::from(
832+
json!({
833+
"privy_token": "not-a-valid-privy-token",
834+
"privy_did": privy_did,
835+
"stellar_address": stellar_addr
836+
})
837+
.to_string(),
838+
))
839+
.unwrap();
840+
841+
let response = create_test_app(pool).oneshot(request).await.unwrap();
842+
843+
assert_eq!(response.status(), StatusCode::UNAUTHORIZED);
844+
}
742845
}

0 commit comments

Comments
 (0)