diff --git a/pom.xml b/pom.xml
index 70794c5..2af6fcd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,7 +18,7 @@
maven-surefire-plugin
3.5.3
- false
+ true
diff --git a/src/main/java/org/privacyidea/AsyncRequestCallable.java b/src/main/java/org/privacyidea/AsyncRequestCallable.java
index 21a0961..1388e4b 100644
--- a/src/main/java/org/privacyidea/AsyncRequestCallable.java
+++ b/src/main/java/org/privacyidea/AsyncRequestCallable.java
@@ -77,14 +77,15 @@ public void onFailure(@NotNull Call call, @NotNull IOException e)
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException
{
- // Only response.body() is available in OkHttp; ensure it is closed and consumed only once to prevent resource leaks.
+ // The body of the response can be in `body()` for success cases or in `errorBody()` for error cases.
+ // We need to handle both and ensure the body is closed to prevent resource leaks.
// The body can only be consumed once.
try (ResponseBody responseBody = response.body())
{
if (responseBody != null)
{
String s = responseBody.string();
- if (!privacyIDEA.logExcludedEndpoints().contains(path) && !ENDPOINT_AUTH.equals(path))
+ if (!privacyIDEA.logExcludedEndpoints().contains(path))
{
privacyIDEA.log(path + " (" + response.code() + "):\n" + privacyIDEA.parser.formatJson(s));
}
diff --git a/src/main/java/org/privacyidea/PIResponse.java b/src/main/java/org/privacyidea/PIResponse.java
index 8b277f7..481a116 100644
--- a/src/main/java/org/privacyidea/PIResponse.java
+++ b/src/main/java/org/privacyidea/PIResponse.java
@@ -18,6 +18,11 @@
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
@@ -84,10 +89,11 @@ public boolean authenticationSuccessful()
*/
public boolean pushAvailable()
{
- return multiChallenge.stream().anyMatch(c -> isPushOrSmartphoneContainer(c.getType()));
+ return multiChallenge.stream().anyMatch(c -> isPushOrSmartphoneContainer(c.getType()) && "poll".equals(c.getClientMode()));
}
- private boolean isPushOrSmartphoneContainer(String type) {
+ private boolean isPushOrSmartphoneContainer(String type)
+ {
return TOKEN_TYPE_PUSH.equals(type) || CONTAINER_TYPE_SMARTPHONE.equals(type);
}
@@ -113,7 +119,8 @@ public String otpTransactionId()
return null;
}
- public String pushTransactionId() {
+ public String pushTransactionId()
+ {
for (Challenge challenge : multiChallenge)
{
if (isPushOrSmartphoneContainer(challenge.getType()))
@@ -142,16 +149,27 @@ private boolean isNotBlank(String str) {
*/
public String otpMessage()
{
- return reduceChallengeMessagesWhere(c -> !(isPushOrSmartphoneContainer(c.getType())));
+ return reduceChallengeMessagesWhere(c ->
+ {
+ String cm = c.getClientMode();
+ System.out.println(
+ "challenge for " + c.getType() + " " + c.getSerial() + " with mode: " + cm);
+ boolean yes = "interactive".equals(cm);
+ return yes;
+ });
}
private String reduceChallengeMessagesWhere(Predicate predicate)
{
StringBuilder sb = new StringBuilder();
- sb.append(
- multiChallenge.stream().filter(predicate).map(Challenge::getMessage).distinct().reduce("", (a, s) -> a + s + ", ").trim());
-
- if (sb.length() > 0)
+ sb.append(this.multiChallenge.stream()
+ .filter(predicate)
+ .map(Challenge::getMessage)
+ .distinct()
+ .reduce("", (a, s) -> a + s + ", ")
+ .trim());
+
+ if (!sb.isEmpty())
{
sb.deleteCharAt(sb.length() - 1);
}
@@ -198,7 +216,19 @@ public String toJSON()
public static PIResponse fromJSON(String json)
{
- return new Gson().fromJson(json, PIResponse.class);
+ JsonDeserializer challengeDeserializer = (jsonElement, type, ctx) ->
+ {
+ JsonObject obj = jsonElement.getAsJsonObject();
+ String serial = obj.has("serial") && !obj.get("serial").isJsonNull() ? obj.get("serial").getAsString() : "";
+ String message = obj.has("message") && !obj.get("message").isJsonNull() ? obj.get("message").getAsString() : "";
+ String clientMode = obj.has("clientMode") && !obj.get("clientMode").isJsonNull() ? obj.get("clientMode").getAsString() : "";
+ String image = obj.has("image") && !obj.get("image").isJsonNull() ? obj.get("image").getAsString() : "";
+ String transactionID = obj.has("transactionID") && !obj.get("transactionID").isJsonNull() ? obj.get("transactionID").getAsString() : "";
+ String tokenType = obj.has("type") && !obj.get("type").isJsonNull() ? obj.get("type").getAsString() : "";
+ return new Challenge(serial, message, clientMode, image, transactionID, tokenType);
+ };
+ Gson gson = new GsonBuilder().registerTypeAdapter(Challenge.class, challengeDeserializer).create();
+ return gson.fromJson(json, PIResponse.class);
}
@Override