commit 0dbf8467b074c683a6ba7e28ac8e10965870ba68
parent 70ba61ef26d99196ab86ff8564d0ed107ff06578
Author: Henrique Chan Carvalho Machado <henriqueccmachado@tecnico.ulisboa.pt>
Date: Sun, 23 Nov 2025 16:53:03 +0100
documentation: cleanup old diagrams, old db tests
Diffstat:
4 files changed, 5 insertions(+), 367 deletions(-)
diff --git a/documentation/onboarding_verifier.pdf b/documentation/onboarding_verifier.pdf
Binary files differ.
diff --git a/documentation/sequence_diagrams/swiyu_taler_sequence_diagram.txt b/documentation/sequence_diagrams/swiyu_taler_sequence_diagram.txt
@@ -25,8 +25,10 @@ sequenceDiagram
Browser ->> Oauth2Gateway: Poll Verification Status
Browser ->> SwiyuWallet: Open $VERIFICATION_URL
- SwiyuWallet ->> SwiyuVerifier: GET /oid4vp/api/request-object/{request_id}
- SwiyuVerifier -->> SwiyuWallet: OID4VP Request Object (DCQL query)
+ SwiyuWallet ->> SwiyuVerifier: GET /oid4vp/api/request-object/{request_id} (DCQL Query)
+ SwiyuVerifier -->> SwiyuWallet: verification presentation definition
+ SwiyuWallet ->> SwiyuVerifier: GET verifier_metadata
+ SwiyuVerifier -->> SwiyuWallet: return metadata
SwiyuWallet ->> SwiyuWallet: Grant Permission
SwiyuWallet ->> SwiyuVerifier: POST /oid4vp/api/request-object/{request_id}/response-data (VP Token)
@@ -47,3 +49,4 @@ sequenceDiagram
Exchange -->> TalerWallet: Notify success
TalerWallet ->> Exchange: Retry original operation
+
diff --git a/documentation/swiyu_taler_sequence_diagram.txt b/documentation/swiyu_taler_sequence_diagram.txt
@@ -1,49 +0,0 @@
-title [Tentative] Swiyu-Taler Interaction
-
-entryspacing 1.2
-participantgroup Taler User
-participant Browser
-participant TalerWallet
-participant Exchange
-participant Oauth2Gateway
-participant SwiyuVerifier
-participant SwiyuWallet
-
-TalerWallet->Exchange: Initiate KYC-required operation
-Exchange->TalerWallet: Send verification link
-TalerWallet->Browser: Open link
-Browser->Exchange: Select verification method (Swiyu)
-
-note over Exchange,Oauth2Gateway: Exchange initiates KYC verification process
-Exchange->Oauth2Gateway: POST /setup/$CLIENT_ID;
-Oauth2Gateway->Exchange: $NONCE
-Exchange->Browser: Send /authorize endpoint
-Browser->Oauth2Gateway: GET /authorize/$NONCE...
-Oauth2Gateway->SwiyuVerifier: POST /management/api/verifications
-SwiyuVerifier->Oauth2Gateway: $VERIFICATION_URL, $REQUEST_ID
-Oauth2Gateway->Browser: Send $VERIFICATION_URL
-Browser->Oauth2Gateway: Poll Verification Status
-Browser->SwiyuWallet: Open $VERIFICATION_URL
-SwiyuWallet->SwiyuVerifier: GET /oid4vp/api/request-object/{request_id}
-SwiyuVerifier->SwiyuWallet: OID4VP Request Object (DCQL query)
-SwiyuWallet->SwiyuWallet: Grant Permission
-SwiyuWallet->SwiyuVerifier: POST /oid4vp/api/request-object/{request_id}/response-data (VP Token)
-
-note over Oauth2Gateway,Exchange: Oauth2Gateway receives webhook and checks verification status
-SwiyuVerifier->Oauth2Gateway: POST /notification {verification_id, timestamp}
-Oauth2Gateway->SwiyuVerifier: GET /management/api/verifications/{verification_id}
-SwiyuVerifier->Oauth2Gateway: {state: SUCCESS/FAILED/PENDING, wallet_response}
-Oauth2Gateway->Browser: Notify verification result
-Oauth2Gateway->Exchange: POST /oauth2gw/kyc/notify/$CLIENT_ID {status}
-
-note over Exchange,Oauth2Gateway: Exchange retrieves the final proof (Verifiable Credential)
-Exchange->Oauth2Gateway: POST /token
-Oauth2Gateway->Exchange: Access token
-Exchange->Oauth2Gateway: GET /info (with access token)
-Oauth2Gateway->SwiyuVerifier: GET /management/api/verifications/{verificationId}
-SwiyuVerifier->Oauth2Gateway: Send proof (Verifiable Credential)
-Oauth2Gateway->Exchange: Send proof (in response body)
-
-Exchange->TalerWallet: Notify success
-TalerWallet->Exchange: Retry original operation
-
diff --git a/oauth2_gateway/tests/api_tests.rs b/oauth2_gateway/tests/api_tests.rs
@@ -1,315 +0,0 @@
-use axum::{routing::*, Router};
-use axum_test::TestServer;
-use oauth2_gateway::{config::*, db, handlers, models::*, state::AppState};
-use serde_json::json;
-use wiremock::{MockServer, Mock, ResponseTemplate};
-use wiremock::matchers::{method, path};
-use serial_test::serial;
-
-
-// API endpoint tests with Mocked Swiyu API and Database
-
-/// Helper to get test database URL
-fn get_test_database_url() -> String {
- std::env::var("TEST_DATABASE_URL")
- .unwrap_or_else(|_| "postgresql://oauth2gw:password@localhost:5432/oauth2gw".to_string())
-}
-
-/// Helper to setup test database and clean data
-async fn setup_test_db() -> sqlx::PgPool {
- let pool = db::create_pool(&get_test_database_url())
- .await
- .expect("Failed to connect to test database");
- clean_test_data(&pool).await;
- pool
-}
-
-/// Clean all test data (in correct FK order)
-async fn clean_test_data(pool: &sqlx::PgPool) {
- sqlx::query("DELETE FROM oauth2gw.notification_logs")
- .execute(pool)
- .await
- .expect("Failed to clean notification_logs");
- sqlx::query("DELETE FROM oauth2gw.webhook_logs")
- .execute(pool)
- .await
- .expect("Failed to clean webhook_logs");
- sqlx::query("DELETE FROM oauth2gw.access_tokens")
- .execute(pool)
- .await
- .expect("Failed to clean access_tokens");
- sqlx::query("DELETE FROM oauth2gw.verification_sessions")
- .execute(pool)
- .await
- .expect("Failed to clean verification_sessions");
- sqlx::query("DELETE FROM oauth2gw.clients")
- .execute(pool)
- .await
- .expect("Failed to clean clients");
-}
-
-/// Helper to teardown test database
-async fn teardown_test_db(pool: &sqlx::PgPool) {
- clean_test_data(pool).await;
-}
-
-/// Create test app with custom verifier base URL (for mock server)
-async fn create_test_app(pool: sqlx::PgPool) -> Router {
- let config = Config {
- server: ServerConfig {
- host: "127.0.0.1".to_string(),
- port: 9090,
- },
- database: DatabaseConfig {
- url: get_test_database_url(),
- },
- };
-
- let state = AppState::new(config, pool);
-
- Router::new()
- .route("/health", get(handlers::health_check))
- .route("/setup/{client_id}", post(handlers::setup))
- .route("/authorize/{nonce}", get(handlers::authorize))
- .route("/token", post(handlers::token))
- .route("/info", get(handlers::info))
- .route("/notification/{client_id}", post(handlers::notification_webhook))
- .with_state(state)
-}
-
-#[tokio::test]
-#[serial]
-async fn test_setup_with_real_database() {
- let pool = setup_test_db().await;
-
- db::clients::register_client(
- &pool,
- "test-client-1",
- "secret123",
- "https://client.example.com/notify",
- "https://verifier.example.com",
- None,
- )
- .await
- .expect("Failed to register client");
-
- let app = create_test_app(pool.clone()).await;
- let server = TestServer::new(app).unwrap();
-
- let response = server
- .post("/setup/test-client-1")
- .json(&json!({"scope": "first_name last_name date_of_birth"}))
- .await;
-
- response.assert_status_ok();
- let body: SetupResponse = response.json();
- assert!(!body.nonce.is_empty());
-
- let session = db::sessions::get_session_by_nonce(&pool, &body.nonce)
- .await
- .expect("Failed to query session")
- .expect("Session not found");
-
- assert_eq!(session.scope, "first_name last_name date_of_birth");
- assert_eq!(session.status, db::sessions::SessionStatus::Pending);
-
- teardown_test_db(&pool).await;
-}
-
-#[tokio::test]
-#[serial]
-async fn test_setup_with_nonexistent_client() {
- let pool = setup_test_db().await;
- let app = create_test_app(pool.clone()).await;
- let server = TestServer::new(app).unwrap();
-
- let response = server
- .post("/setup/nonexistent-client")
- .json(&json!({"scope": "test"}))
- .await;
-
- response.assert_status(axum::http::StatusCode::NOT_FOUND);
- let body: ErrorResponse = response.json();
- assert_eq!(body.error, "client_not_found");
-
- teardown_test_db(&pool).await;
-}
-
-#[tokio::test]
-#[serial]
-async fn test_authorize_successful_flow_with_mocked_swiyu() {
- let pool = setup_test_db().await;
-
- let mock_server = MockServer::start().await;
-
- db::clients::register_client(
- &pool,
- "test-client-2",
- "secret123",
- "https://client.example.com/notify",
- &mock_server.uri(), // Use mock verifier
- Some("/management/api/verifications"),
- )
- .await
- .expect("Failed to register client");
-
- // mock Swiyu response
- Mock::given(method("POST"))
- .and(path("/management/api/verifications"))
- .respond_with(ResponseTemplate::new(200).set_body_json(json!({
- "id": "550e8400-e29b-41d4-a716-446655440000",
- "verification_url": "https://wallet.example.com/verify?request=abc123",
- "verification_deeplink": "swiyu://verify/abc123",
- "state": "PENDING",
- "presentation_definition": {
- "id": "test-pd-id",
- "input_descriptors": []
- }
- })))
- .mount(&mock_server)
- .await;
-
- let app = create_test_app(pool.clone()).await;
- let server = TestServer::new(app).unwrap();
-
- let setup_response = server
- .post("/setup/test-client-2")
- .json(&json!({"scope": "first_name last_name"}))
- .await;
-
- setup_response.assert_status_ok();
- let setup: SetupResponse = setup_response.json();
-
- // Call authorize
- let response = server
- .get(&format!("/authorize/{}", setup.nonce))
- .await;
-
- response.assert_status_ok();
- let body: AuthorizeResponse = response.json();
-
- assert_eq!(body.verification_url, "https://wallet.example.com/verify?request=abc123");
- assert_eq!(body.verification_id.to_string(), "550e8400-e29b-41d4-a716-446655440000");
-
- let session = db::sessions::get_session_by_nonce(&pool, &setup.nonce)
- .await
- .expect("Failed to query session")
- .expect("Session not found");
-
- assert_eq!(session.status, db::sessions::SessionStatus::Authorized);
- assert_eq!(session.verification_url, Some("https://wallet.example.com/verify?request=abc123".to_string()));
- assert_eq!(session.request_id, Some("550e8400-e29b-41d4-a716-446655440000".to_string()));
-
- teardown_test_db(&pool).await;
-}
-
-#[tokio::test]
-#[serial]
-async fn test_authorize_with_invalid_nonce() {
- let pool = setup_test_db().await;
- let app = create_test_app(pool.clone()).await;
- let server = TestServer::new(app).unwrap();
-
- let response = server
- .get("/authorize/invalid-nonce-12345")
- .await;
-
- response.assert_status(axum::http::StatusCode::NOT_FOUND);
- let body: ErrorResponse = response.json();
- assert_eq!(body.error, "session_not_found");
-
- teardown_test_db(&pool).await;
-}
-
-#[tokio::test]
-#[serial]
-async fn test_authorize_with_expired_session() {
- let pool = setup_test_db().await;
-
- let client = db::clients::register_client(
- &pool,
- "test-client-3",
- "secret123",
- "https://client.example.com/notify",
- "https://verifier.example.com",
- None,
- )
- .await
- .expect("Failed to register client");
-
- // Create expired session (negative expiration)
- sqlx::query(
- r#"
- INSERT INTO oauth2gw.verification_sessions (client_id, nonce, scope, expires_at, status)
- VALUES ($1, $2, $3, CURRENT_TIMESTAMP - INTERVAL '1 hour', 'pending')
- "#
- )
- .bind(client.id)
- .bind("expired-nonce")
- .bind("test")
- .execute(&pool)
- .await
- .expect("Failed to create expired session");
-
- let app = create_test_app(pool.clone()).await;
- let server = TestServer::new(app).unwrap();
-
- let response = server
- .get("/authorize/expired-nonce")
- .await;
-
- response.assert_status(axum::http::StatusCode::BAD_REQUEST);
- let body: ErrorResponse = response.json();
- assert_eq!(body.error, "session_expired");
-
- teardown_test_db(&pool).await;
-}
-
-#[tokio::test]
-#[serial]
-async fn test_authorize_with_swiyu_api_error() {
- let pool = setup_test_db().await;
- let mock_server = MockServer::start().await;
-
-
- db::clients::register_client(
- &pool,
- "test-client-4",
- "secret123",
- "https://client.example.com/notify",
- &mock_server.uri(),
- Some("/management/api/verifications"),
- )
- .await
- .expect("Failed to register client");
-
- // mock Swiyu response
- Mock::given(method("POST"))
- .and(path("/management/api/verifications"))
- .respond_with(ResponseTemplate::new(500).set_body_json(json!({
- "error": "internal_server_error"
- })))
- .mount(&mock_server)
- .await;
-
- let app = create_test_app(pool.clone()).await;
- let server = TestServer::new(app).unwrap();
-
- // Setup and authorize
- let setup_response = server
- .post("/setup/test-client-4")
- .json(&json!({"scope": "test"}))
- .await;
-
- let setup: SetupResponse = setup_response.json();
-
- let response = server
- .get(&format!("/authorize/{}", setup.nonce))
- .await;
-
- response.assert_status(axum::http::StatusCode::BAD_GATEWAY);
- let body: ErrorResponse = response.json();
- assert_eq!(body.error, "verifier_error");
-
- teardown_test_db(&pool).await;
-}
-\ No newline at end of file