kych

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

commit 9a43600b7add2643f4397fa45766dbfdd5d6562f
parent c1a72c659fb4be558d2e2f78e7821a525ce41888
Author: Henrique Chan Carvalho Machado <henriqueccmachado@tecnico.ulisboa.pt>
Date:   Mon, 19 Jan 2026 22:37:56 +0100

Refactor Accepted Issuer DIDs

Changed parsing of accpeted issuer dids. Fix bug, now uses configured accepted
issuer dids only. Allows multiple issuer dids to be configured.

Diffstat:
Mkych_oauth2_gateway/kych.conf.example | 4++--
Mkych_oauth2_gateway/src/bin/client_management_cli.rs | 2+-
Mkych_oauth2_gateway/src/db/sessions.rs | 5++++-
Mkych_oauth2_gateway/src/handlers.rs | 45++++++++++++++++++++++++++++++++++++++++++++-
Mkych_oauth2_gateway/src/models.rs | 6------
5 files changed, 51 insertions(+), 11 deletions(-)

diff --git a/kych_oauth2_gateway/kych.conf.example b/kych_oauth2_gateway/kych.conf.example @@ -18,7 +18,7 @@ CLIENT_SECRET = secret VERIFIER_URL = https://swiyu-verifier9999.ch VERIFIER_MANAGEMENT_API_PATH = /management/api/verifications REDIRECT_URI = https://kych-oauth2-gateway-client.com/kych-providers/kych-redirect -ACCEPTED_ISSUER_DIDS = did:tdw:trust_this_issuer +ACCEPTED_ISSUER_DIDS = {did:tdw:trust_this_issuer} # [client_2] # CLIENT_ID = client_staging_01 @@ -26,4 +26,4 @@ ACCEPTED_ISSUER_DIDS = did:tdw:trust_this_issuer # VERIFIER_URL = https://verifier-staging.example.com # VERIFIER_MANAGEMENT_API_PATH = /api/v1/verifications # REDIRECT_URI = https://staging.example.com/callback -# ACCEPTED_ISSUER_DIDS = did:key:staging1 +# ACCEPTED_ISSUER_DIDS = {did:key:staging1} diff --git a/kych_oauth2_gateway/src/bin/client_management_cli.rs b/kych_oauth2_gateway/src/bin/client_management_cli.rs @@ -57,7 +57,7 @@ enum Commands { #[arg(long)] redirect_uri: String, - /// Comma-separated list of accepted issuer DIDs + /// Accepted issuer DIDs in braces, e.g. {did1, did2} #[arg(long)] accepted_issuer_dids: Option<String>, }, diff --git a/kych_oauth2_gateway/src/db/sessions.rs b/kych_oauth2_gateway/src/db/sessions.rs @@ -62,6 +62,7 @@ pub struct AuthorizeSessionData { pub verifier_url: String, pub verifier_management_api_path: String, pub allowed_redirect_uris: Option<String>, + pub accepted_issuer_dids: Option<String>, } /// Notification record data used in /notification webhook endpoint @@ -158,7 +159,8 @@ pub async fn get_session_for_authorize( s.verifier_nonce, c.verifier_url, c.verifier_management_api_path, - c.redirect_uri AS allowed_redirect_uris + c.redirect_uri AS allowed_redirect_uris, + c.accepted_issuer_dids "# ) .bind(nonce) @@ -185,6 +187,7 @@ pub async fn get_session_for_authorize( verifier_url: row.get("verifier_url"), verifier_management_api_path: row.get("verifier_management_api_path"), allowed_redirect_uris: row.get("allowed_redirect_uris"), + accepted_issuer_dids: row.get("accepted_issuer_dids"), } })) } diff --git a/kych_oauth2_gateway/src/handlers.rs b/kych_oauth2_gateway/src/handlers.rs @@ -28,6 +28,29 @@ fn json_encode_string(s: &str) -> String { serde_json::to_string(s).unwrap_or_else(|_| "\"\"".to_string()) } +fn parse_accepted_issuer_dids(raw: &str) -> Result<Vec<String>, &'static str> { + let trimmed = raw.trim(); + if trimmed.is_empty() { + return Err("ACCEPTED_ISSUER_DIDS must contain at least one DID"); + } + + let trimmed = trimmed.strip_prefix('{').unwrap_or(trimmed); + let trimmed = trimmed.strip_suffix('}').unwrap_or(trimmed); + + let dids: Vec<String> = trimmed + .split(',') + .map(|s| s.trim()) + .filter(|s| !s.is_empty()) + .map(|s| s.to_string()) + .collect(); + + if dids.is_empty() { + return Err("ACCEPTED_ISSUER_DIDS must contain at least one DID"); + } + + Ok(dids) +} + // Health check endpoint pub async fn health_check() -> impl IntoResponse { tracing::info!("Received Health Request"); @@ -347,8 +370,28 @@ pub async fn authorize( // Call Swiyu Verifier let verifier_url = format!("{}{}", data.verifier_url, data.verifier_management_api_path); + let accepted_issuer_dids = match data.accepted_issuer_dids.as_deref() { + Some(raw) => parse_accepted_issuer_dids(raw).map_err(|message| { + tracing::error!("Invalid accepted issuer DIDs for client {}: {}", params.client_id, message); + ( + StatusCode::INTERNAL_SERVER_ERROR, + Json(ErrorResponse::new("invalid_accepted_issuer_dids")), + ) + })?, + None => { + tracing::error!( + "Accepted issuer DIDs not configured for client {}", + params.client_id + ); + return Err(( + StatusCode::INTERNAL_SERVER_ERROR, + Json(ErrorResponse::new("accepted_issuer_dids_not_configured")), + )); + } + }; + let verifier_request = SwiyuCreateVerificationRequest { - accepted_issuer_dids: default_accepted_issuer_dids(), + accepted_issuer_dids, trust_anchors: None, jwt_secured_authorization_request: Some(true), response_mode: ResponseMode::DirectPost, diff --git a/kych_oauth2_gateway/src/models.rs b/kych_oauth2_gateway/src/models.rs @@ -118,16 +118,10 @@ impl ErrorResponse { // Swiyu Verifier API models -/// Default issuer DID for Swiyu verification -pub fn default_accepted_issuer_dids() -> Vec<String> { - vec!["did:tdw:QmPEZPhDFR4nEYSFK5bMnvECqdpf1tPTPJuWs9QrMjCumw:identifier-reg.trust-infra.swiyu-int.admin.ch:api:v1:did:9a5559f0-b81c-4368-a170-e7b4ae424527".to_string()] -} - /// Request body for creating a verification with Swiyu Verifier /// POST /management/api/verifications #[derive(Debug, Serialize, Deserialize)] pub struct SwiyuCreateVerificationRequest { - #[serde(default = "default_accepted_issuer_dids")] pub accepted_issuer_dids: Vec<String>, #[serde(skip_serializing_if = "Option::is_none")] pub trust_anchors: Option<Vec<TrustAnchor>>,