diff --git a/pom.xml b/pom.xml index a5ce3c7..70794c5 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 org.privacyidea privacyidea-java-client - 1.4.0 + 1.5.0 jar UTF-8 @@ -83,16 +83,16 @@ 4.13.2 test - - com.squareup.okhttp3 - okhttp - 4.12.0 - org.jetbrains.kotlin kotlin-stdlib 1.9.0 + + com.squareup.okhttp3 + okhttp + 4.12.0 + com.squareup.okio okio diff --git a/src/main/java/org/privacyidea/AsyncRequestCallable.java b/src/main/java/org/privacyidea/AsyncRequestCallable.java index 46495a0..21a0961 100644 --- a/src/main/java/org/privacyidea/AsyncRequestCallable.java +++ b/src/main/java/org/privacyidea/AsyncRequestCallable.java @@ -24,6 +24,7 @@ import okhttp3.Call; import okhttp3.Callback; import okhttp3.Response; +import okhttp3.ResponseBody; import org.jetbrains.annotations.NotNull; import static org.privacyidea.PIConstants.ENDPOINT_AUTH; @@ -76,15 +77,22 @@ public void onFailure(@NotNull Call call, @NotNull IOException e) @Override public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { - if (response.body() != null) + // Only response.body() is available in OkHttp; ensure it is closed and consumed only once to prevent resource leaks. + // The body can only be consumed once. + try (ResponseBody responseBody = response.body()) { - String s = response.body().string(); - if (!privacyIDEA.logExcludedEndpoints().contains(path) && !ENDPOINT_AUTH.equals(path)) + if (responseBody != null) { - privacyIDEA.log(path + ":\n" + privacyIDEA.parser.formatJson(s)); + String s = responseBody.string(); + if (!privacyIDEA.logExcludedEndpoints().contains(path) && !ENDPOINT_AUTH.equals(path)) + { + privacyIDEA.log(path + " (" + response.code() + "):\n" + privacyIDEA.parser.formatJson(s)); + } + callbackResult[0] = s; } - callbackResult[0] = s; } - latch.countDown(); + finally { + latch.countDown(); + } } } \ No newline at end of file diff --git a/src/main/java/org/privacyidea/JSONParser.java b/src/main/java/org/privacyidea/JSONParser.java index f67ea71..e065ea7 100644 --- a/src/main/java/org/privacyidea/JSONParser.java +++ b/src/main/java/org/privacyidea/JSONParser.java @@ -73,6 +73,7 @@ import static org.privacyidea.PIConstants.TIME; import static org.privacyidea.PIConstants.TOKEN; import static org.privacyidea.PIConstants.TOKENS; +import static org.privacyidea.PIConstants.TOKEN_TYPE_PASSKEY; import static org.privacyidea.PIConstants.TOKEN_TYPE_WEBAUTHN; import static org.privacyidea.PIConstants.TRANSACTION_ID; import static org.privacyidea.PIConstants.TYPE; @@ -277,6 +278,7 @@ else if ("interactive".equals(modeFromResponse)) }); } + // Multichallenge JsonArray arrChallenges = detail.getAsJsonArray(MULTI_CHALLENGE); if (arrChallenges != null) { @@ -311,6 +313,10 @@ else if ("interactive".equals(modeFromResponse)) webauthnSignRequests.add(webauthnSignRequest); } } + else if (TOKEN_TYPE_PASSKEY.equals(type)) + { + response.passkeyChallenge = challenge.toString(); + } else { response.multiChallenge.add(new Challenge(serial, message, clientMode, image, transactionID, type)); diff --git a/src/main/java/org/privacyidea/PIResponse.java b/src/main/java/org/privacyidea/PIResponse.java index 534ac74..8b277f7 100644 --- a/src/main/java/org/privacyidea/PIResponse.java +++ b/src/main/java/org/privacyidea/PIResponse.java @@ -124,6 +124,17 @@ public String pushTransactionId() { return null; } + public boolean hasChallenges() + { + return (multiChallenge != null && !multiChallenge.isEmpty()) || + isNotBlank(mergedSignRequest()) || + isNotBlank(passkeyChallenge); + } + + private boolean isNotBlank(String str) { + return str != null && !str.trim().isEmpty(); + } + /** * Get the messages of all token that require an input field (HOTP, TOTP, SMS, Email...) reduced to a single string. *