From 40daca36a035627cb1be7075d537db652f78af13 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Mon, 27 Apr 2026 08:45:45 +0200 Subject: [PATCH] feat: add WebAuthn credential and custom data methods to LogtoManagementClient --- .../saas/identity/LogtoManagementClient.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/main/java/net/siegeln/cameleer/saas/identity/LogtoManagementClient.java b/src/main/java/net/siegeln/cameleer/saas/identity/LogtoManagementClient.java index 79806fc..26a91f4 100644 --- a/src/main/java/net/siegeln/cameleer/saas/identity/LogtoManagementClient.java +++ b/src/main/java/net/siegeln/cameleer/saas/identity/LogtoManagementClient.java @@ -604,6 +604,47 @@ public class LogtoManagementClient { } } + /** List WebAuthn credentials for a user (filtered from all MFA verifications). */ + @SuppressWarnings("unchecked") + public List> getWebAuthnCredentials(String userId) { + var all = getUserMfaVerifications(userId); + return all.stream() + .filter(v -> "WebAuthn".equals(String.valueOf(v.get("type")))) + .toList(); + } + + /** Rename a WebAuthn credential. Uses PATCH on the MFA verification. */ + public void renameMfaVerification(String userId, String verificationId, String name) { + if (!isAvailable()) return; + try { + restClient.patch() + .uri(config.getLogtoEndpoint() + "/api/users/" + userId + "/mfa-verifications/" + verificationId) + .header("Authorization", "Bearer " + getAccessToken()) + .contentType(MediaType.APPLICATION_JSON) + .body(Map.of("name", name)) + .retrieve() + .toBodilessEntity(); + } catch (Exception e) { + log.warn("Failed to rename MFA verification {} for user {}: {}", verificationId, userId, e.getMessage()); + } + } + + /** Update user custom data (partial merge). Used for mfa_method_preference. */ + public void updateUserCustomData(String userId, Map customData) { + if (!isAvailable()) return; + try { + restClient.patch() + .uri(config.getLogtoEndpoint() + "/api/users/" + userId + "/custom-data") + .header("Authorization", "Bearer " + getAccessToken()) + .contentType(MediaType.APPLICATION_JSON) + .body(customData) + .retrieve() + .toBodilessEntity(); + } catch (Exception e) { + log.warn("Failed to update custom data for user {}: {}", userId, e.getMessage()); + } + } + /** Update a user's profile fields (e.g. name). */ public void updateUserProfile(String userId, Map profile) { if (!isAvailable()) throw new IllegalStateException("Logto not configured");