feat: add MFA Management API methods to LogtoManagementClient

Add 5 new methods for MFA operations via Logto Management API:
- getUserMfaVerifications: list all MFA factors for a user
- createTotpVerification: create TOTP MFA verification
- createBackupCodes: generate backup codes
- deleteMfaVerification: delete a specific MFA verification
- deleteAllMfaVerifications: delete all MFA verifications (admin reset)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-26 13:48:29 +02:00
parent 66477ff575
commit 94de4c2a5b

View File

@@ -526,6 +526,84 @@ public class LogtoManagementClient {
.toBodilessEntity();
}
// --- MFA Verification Management ---
/** List all MFA verifications for a user. Returns a list of MFA factor objects. */
@SuppressWarnings("unchecked")
public List<Map<String, Object>> getUserMfaVerifications(String userId) {
if (!isAvailable()) return List.of();
try {
var resp = restClient.get()
.uri(config.getLogtoEndpoint() + "/api/users/" + userId + "/mfa-verifications")
.header("Authorization", "Bearer " + getAccessToken())
.retrieve()
.body(List.class);
return resp != null ? resp : List.of();
} catch (Exception e) {
log.warn("Failed to get MFA verifications for user {}: {}", userId, e.getMessage());
return List.of();
}
}
/** Create a TOTP MFA verification for a user. Returns the secret and QR code. */
@SuppressWarnings("unchecked")
public Map<String, Object> createTotpVerification(String userId, String secret) {
if (!isAvailable()) return Map.of();
try {
return (Map<String, Object>) restClient.post()
.uri(config.getLogtoEndpoint() + "/api/users/" + userId + "/mfa-verifications")
.header("Authorization", "Bearer " + getAccessToken())
.contentType(MediaType.APPLICATION_JSON)
.body(Map.of("type", "Totp", "secret", secret))
.retrieve()
.body(Map.class);
} catch (Exception e) {
log.warn("Failed to create TOTP verification for user {}: {}", userId, e.getMessage());
return Map.of();
}
}
/** Generate backup codes for a user. Returns the list of codes. */
@SuppressWarnings("unchecked")
public Map<String, Object> createBackupCodes(String userId) {
if (!isAvailable()) return Map.of();
try {
return (Map<String, Object>) restClient.post()
.uri(config.getLogtoEndpoint() + "/api/users/" + userId + "/mfa-verifications")
.header("Authorization", "Bearer " + getAccessToken())
.contentType(MediaType.APPLICATION_JSON)
.body(Map.of("type", "BackupCode"))
.retrieve()
.body(Map.class);
} catch (Exception e) {
log.warn("Failed to create backup codes for user {}: {}", userId, e.getMessage());
return Map.of();
}
}
/** Delete a specific MFA verification for a user. */
public void deleteMfaVerification(String userId, String verificationId) {
if (!isAvailable()) return;
try {
restClient.delete()
.uri(config.getLogtoEndpoint() + "/api/users/" + userId + "/mfa-verifications/" + verificationId)
.header("Authorization", "Bearer " + getAccessToken())
.retrieve()
.toBodilessEntity();
} catch (Exception e) {
log.warn("Failed to delete MFA verification {} for user {}: {}", verificationId, userId, e.getMessage());
}
}
/** Delete all MFA verifications for a user (used for admin MFA reset). */
public void deleteAllMfaVerifications(String userId) {
List<Map<String, Object>> verifications = getUserMfaVerifications(userId);
for (Map<String, Object> v : verifications) {
String id = String.valueOf(v.get("id"));
deleteMfaVerification(userId, id);
}
}
/** Update a user's profile fields (e.g. name). */
public void updateUserProfile(String userId, Map<String, Object> profile) {
if (!isAvailable()) throw new IllegalStateException("Logto not configured");