kych

OAuth 2.0 API for Swiyu to enable Taler integration of Swiyu for KYC (experimental)
Log | Files | Refs | README

commit 4d72952ac96ecc9451b31f6a79e621ba9655bdd5
parent fc7d5c43b0512c61d7a185b67d53b3ecf2b0548f
Author: Henrique Chan Carvalho Machado <henriqueccmachado@tecnico.ulisboa.pt>
Date:   Wed, 21 Jan 2026 18:37:43 +0100

Replace health check with /config endpoint exposing VC configuration

Replaced the /health endpoint with /config to return application and VC
configuration. Added ConfigResponse, updated the handler to read from AppState,
sort VC claims, format JSON output, and expose the app version. Updated routing
and integration tests to cover all response fields.

Diffstat:
Mkych_oauth2_gateway/src/handlers.rs | 24+++++++++++++++++-------
Mkych_oauth2_gateway/src/main.rs | 2+-
Mkych_oauth2_gateway/src/models.rs | 11+++++++++++
Mkych_oauth2_gateway/tests/handlers_integration.rs | 18+++++++++++++++---
4 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/kych_oauth2_gateway/src/handlers.rs b/kych_oauth2_gateway/src/handlers.rs @@ -61,13 +61,23 @@ fn validate_scope_claims(scope: &str, valid_claims: &HashSet<String>) -> Result< Ok(()) } -// Health check endpoint -pub async fn health_check() -> impl IntoResponse { - tracing::info!("Received Health Request"); - Json(json!({ - "status": "healthy", - "service": "oauth2-gateway", - })) +pub async fn config( + State(state): State<AppState>, +) -> impl IntoResponse { + tracing::info!("Config request received"); + + let mut claims: Vec<String> = state.config.vc.vc_claims.iter().cloned().collect(); + claims.sort(); + + PrettyJson(ConfigResponse { + name: "kych-oauth2-gateway".to_string(), + version: env!("CARGO_PKG_VERSION").to_string(), + status: "healthy".to_string(), + vc_type: state.config.vc.vc_type.clone(), + vc_format: state.config.vc.vc_format.clone(), + vc_algorithms: state.config.vc.vc_algorithms.clone(), + vc_claims: claims, + }) } // POST /setup/{clientId} diff --git a/kych_oauth2_gateway/src/main.rs b/kych_oauth2_gateway/src/main.rs @@ -53,7 +53,7 @@ async fn main() -> Result<()> { let state = AppState::new(config.clone(), pool); let app = Router::new() - .route("/health", get(handlers::health_check)) + .route("/config", get(handlers::config)) .route("/setup/{client_id}", post(handlers::setup)) .route("/authorize/{nonce}", get(handlers::authorize)) .route("/token", post(handlers::token)) diff --git a/kych_oauth2_gateway/src/models.rs b/kych_oauth2_gateway/src/models.rs @@ -92,6 +92,17 @@ pub struct StatusResponse { pub status: String, } +#[derive(Debug, Serialize)] +pub struct ConfigResponse { + pub name: String, + pub version: String, + pub status: String, + pub vc_type: String, + pub vc_format: String, + pub vc_algorithms: Vec<String>, + pub vc_claims: Vec<String>, +} + // Notification payload sent to Client (Exchange, etc.) #[derive(Debug, Serialize)] pub struct ClientNotification { diff --git a/kych_oauth2_gateway/tests/handlers_integration.rs b/kych_oauth2_gateway/tests/handlers_integration.rs @@ -80,7 +80,7 @@ fn test_config(database_url: &str) -> Config { fn build_app(state: AppState) -> Router { Router::new() - .route("/health", get(handlers::health_check)) + .route("/config", get(handlers::config)) .route("/setup/{client_id}", post(handlers::setup)) .route("/authorize/{nonce}", get(handlers::authorize)) .route("/token", post(handlers::token)) @@ -321,16 +321,28 @@ async fn assert_error_response( } #[tokio::test] -async fn test_health_check() -> Result<()> { +async fn test_config_endpoint() -> Result<()> { let Some(pool) = get_pool().await else { return Ok(()); }; let config = test_config(&std::env::var("DATABASE_URL")?); let app = build_app(AppState::new(config, pool)); let response = app - .oneshot(Request::builder().uri("/health").body(Body::empty())?) + .oneshot(Request::builder().uri("/config").body(Body::empty())?) .await?; assert_eq!(response.status(), StatusCode::OK); + + let bytes = to_bytes(response.into_body(), usize::MAX).await?; + let json: Value = serde_json::from_slice(&bytes)?; + + assert_eq!(json.get("name").and_then(|v| v.as_str()), Some("kych-oauth2-gateway")); + assert!(json.get("version").and_then(|v| v.as_str()).is_some()); + assert_eq!(json.get("status").and_then(|v| v.as_str()), Some("healthy")); + assert_eq!(json.get("vc_type").and_then(|v| v.as_str()), Some("betaid-sdjwt")); + assert_eq!(json.get("vc_format").and_then(|v| v.as_str()), Some("vc+sd-jwt")); + assert!(json.get("vc_algorithms").and_then(|v| v.as_array()).is_some()); + assert!(json.get("vc_claims").and_then(|v| v.as_array()).is_some()); + Ok(()) }