Skip to content

Commit 20d719f

Browse files
authored
Merge pull request #20 from privacyidea/formatting
custom headers, webauthn pinchange
2 parents cd07979 + c43cc4e commit 20d719f

File tree

5 files changed

+152
-56
lines changed

5 files changed

+152
-56
lines changed

src/main/java/org/privacyidea/Endpoint.java

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.nio.charset.StandardCharsets;
2828
import java.security.KeyManagementException;
2929
import java.security.NoSuchAlgorithmException;
30+
import java.util.Arrays;
3031
import java.util.Collections;
3132
import java.util.LinkedHashMap;
3233
import java.util.List;
@@ -60,7 +61,7 @@
6061
class Endpoint {
6162

6263
private final PrivacyIDEA privacyIDEA;
63-
private List<String> logExcludedEndpointPrints = Collections.emptyList(); //Arrays.asList(PIConstants.ENDPOINT_AUTH, PIConstants.ENDPOINT_POLLTRANSACTION); //
64+
private List<String> logExcludedEndpointPrints = Arrays.asList(PIConstants.ENDPOINT_AUTH, PIConstants.ENDPOINT_POLLTRANSACTION); //Collections.emptyList(); //
6465
private final PIConfig piconfig;
6566
private final OkHttpClient client;
6667

@@ -117,9 +118,9 @@ String sendRequest(String endpoint, Map<String, String> params, Map<String, Stri
117118
params.forEach((key, value) -> {
118119
//privacyIDEA.log("" + key + "=" + value);
119120
try {
120-
String enc_value = value;
121-
enc_value = URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
122-
urlBuilder.addQueryParameter(key, enc_value);
121+
String encValue = value;
122+
encValue = URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
123+
urlBuilder.addQueryParameter(key, encValue);
123124
} catch (UnsupportedEncodingException e) {
124125
e.printStackTrace();
125126
}
@@ -150,17 +151,17 @@ String sendRequest(String endpoint, Map<String, String> params, Map<String, Stri
150151
FormBody.Builder formBodyBuilder = new FormBody.Builder();
151152
params.forEach((key, value) -> {
152153
if (key != null && value != null) {
153-
String enc_value = value;
154+
String encValue = value;
154155
// WebAuthn params are excluded from url encoded, they are already in the correct format for the server
155156
if (!WEBAUTHN_PARAMETERS.contains(key)) {
156157
try {
157-
enc_value = URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
158+
encValue = URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
158159
} catch (UnsupportedEncodingException e) {
159160
privacyIDEA.error(e);
160161
}
161162
}
162-
//privacyIDEA.log("" + key + "=" + enc_value);
163-
formBodyBuilder.add(key, enc_value);
163+
//privacyIDEA.log("" + key + "=" + encValue);
164+
formBodyBuilder.add(key, encValue);
164165
}
165166
});
166167
// This switches okhttp to make a post request
@@ -174,7 +175,9 @@ String sendRequest(String endpoint, Map<String, String> params, Map<String, Stri
174175
Response response = client.newCall(request).execute();
175176
if (response.body() != null) {
176177
String ret = response.body().string();
177-
endpointLog(endpoint, ret);
178+
if (!logExcludedEndpointPrints.contains(endpoint)) {
179+
privacyIDEA.log(prettyFormatJson(ret));
180+
}
178181
return ret;
179182
} else {
180183
privacyIDEA.log("Response body is null.");
@@ -188,7 +191,7 @@ String sendRequest(String endpoint, Map<String, String> params, Map<String, Stri
188191

189192
String getAuthTokenFromServer() {
190193
if (!privacyIDEA.checkServiceAccountAvailable()) {
191-
privacyIDEA.log("Service account information not set, cannot retrieve auth token");
194+
privacyIDEA.error("Cannot retrieve auth token from server without service account!");
192195
return "";
193196
}
194197

@@ -206,11 +209,11 @@ String getAuthTokenFromServer() {
206209
if (response != null && !response.isEmpty()) {
207210
JsonElement root = JsonParser.parseString(response);
208211
if (root != null) {
209-
JsonObject obj = root.getAsJsonObject();
210-
if (obj != null) {
212+
try {
213+
JsonObject obj = root.getAsJsonObject();
211214
return obj.getAsJsonObject(RESULT).getAsJsonObject(VALUE).getAsJsonPrimitive(TOKEN).getAsString();
212-
} else {
213-
privacyIDEA.log("Response did not contain an authorization token: " + prettyFormatJson(response));
215+
} catch (Exception e) {
216+
privacyIDEA.error("Response did not contain an authorization token: " + prettyFormatJson(response));
214217
}
215218
}
216219
} else {
@@ -235,12 +238,6 @@ public static String prettyFormatJson(String json) {
235238
return gson.toJson(obj);
236239
}
237240

238-
private void endpointLog(String endpoint, String response) {
239-
if (!logExcludedEndpointPrints.contains(endpoint)) {
240-
privacyIDEA.log(prettyFormatJson(response));
241-
}
242-
}
243-
244241
public List<String> getLogExcludedEndpoints() {
245242
return logExcludedEndpointPrints;
246243
}

src/main/java/org/privacyidea/PIResponse.java

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.google.gson.JsonSyntaxException;
2525
import java.util.ArrayList;
2626
import java.util.List;
27+
import java.util.function.Predicate;
2728
import java.util.stream.Collectors;
2829

2930
import static org.privacyidea.PIConstants.ATTRIBUTES;
@@ -40,6 +41,7 @@
4041
import static org.privacyidea.PIConstants.SERIAL;
4142
import static org.privacyidea.PIConstants.SIGNATURE;
4243
import static org.privacyidea.PIConstants.STATUS;
44+
import static org.privacyidea.PIConstants.TOKEN_TYPE_PUSH;
4345
import static org.privacyidea.PIConstants.TOKEN_TYPE_WEBAUTHN;
4446
import static org.privacyidea.PIConstants.TRANSACTION_ID;
4547
import static org.privacyidea.PIConstants.TYPE;
@@ -130,16 +132,20 @@ public PIResponse(String json) {
130132
for (int i = 0; i < arrChallenges.size(); i++) {
131133
JsonObject challenge = arrChallenges.get(i).getAsJsonObject();
132134
if (TOKEN_TYPE_WEBAUTHN.equals(getString(challenge, TYPE))) {
133-
JsonObject attrObj = challenge.getAsJsonObject(ATTRIBUTES);
134-
if (attrObj != null && !attrObj.isJsonNull()) {
135-
JsonObject webauthnObj = attrObj.getAsJsonObject(WEBAUTHN_SIGN_REQUEST);
136-
multichallenge.add(new WebAuthn(
137-
getString(challenge, SERIAL),
138-
getString(challenge, MESSAGE),
139-
getString(challenge, TRANSACTION_ID),
140-
webauthnObj.toString()
141-
));
135+
String webAuthnSignRequest = "";
136+
JsonElement attrElem = challenge.get(ATTRIBUTES);
137+
if (attrElem != null && !attrElem.isJsonNull()) {
138+
JsonElement webauthnElem = attrElem.getAsJsonObject().get(WEBAUTHN_SIGN_REQUEST);
139+
if (webauthnElem != null && !webauthnElem.isJsonNull()) {
140+
webAuthnSignRequest = webauthnElem.toString();
141+
}
142142
}
143+
multichallenge.add(new WebAuthn(
144+
getString(challenge, SERIAL),
145+
getString(challenge, MESSAGE),
146+
getString(challenge, TRANSACTION_ID),
147+
webAuthnSignRequest
148+
));
143149
} else {
144150
multichallenge.add(new Challenge(
145151
getString(challenge, SERIAL),
@@ -150,7 +156,6 @@ public PIResponse(String json) {
150156
}
151157
}
152158
}
153-
154159
}
155160
}
156161

@@ -190,6 +195,45 @@ public String getMessage() {
190195
return message;
191196
}
192197

198+
public boolean isPushAvailable() {
199+
return multichallenge.stream().anyMatch(c -> TOKEN_TYPE_PUSH.equals(c.getType()));
200+
}
201+
202+
/**
203+
* Get the messages of all triggered push challenges reduced to a string to show on the push UI.
204+
*
205+
* @return messages of all push challenges combined
206+
*/
207+
public String getPushMessage() {
208+
return reduceChallengeMessagesWhere(c -> TOKEN_TYPE_PUSH.equals(c.getType()));
209+
}
210+
211+
/**
212+
* Get the messages of all token that require an input field (HOTP, TOTP, SMS, Email...) reduced to a single string
213+
* to show with the input field.
214+
*
215+
* @return message string
216+
*/
217+
public String getOTPMessage() {
218+
// Any challenge that is not WebAuthn or Push is considered OTP
219+
return reduceChallengeMessagesWhere(c -> !(TOKEN_TYPE_WEBAUTHN.equals(c.getType())) && !(TOKEN_TYPE_PUSH.equals(c.getType())));
220+
}
221+
222+
private String reduceChallengeMessagesWhere(Predicate<Challenge> predicate) {
223+
StringBuilder sb = new StringBuilder();
224+
sb.append(multichallenge
225+
.stream()
226+
.filter(predicate)
227+
.map(Challenge::getMessage)
228+
.reduce("", (a, s) -> a + s + ", ").trim());
229+
230+
if (sb.length() > 0) {
231+
sb.deleteCharAt(sb.length() - 1);
232+
}
233+
234+
return sb.toString();
235+
}
236+
193237
/**
194238
* @return list of token types that were triggered or an empty list
195239
*/
@@ -211,6 +255,21 @@ public List<Challenge> getMultiChallenge() {
211255
return multichallenge;
212256
}
213257

258+
/**
259+
* Get all WebAuthn challenges from the multi_challenge.
260+
*
261+
* @return List of WebAuthn objects or empty list
262+
*/
263+
public List<WebAuthn> getWebAuthnSignRequests() {
264+
List<WebAuthn> ret = new ArrayList<>();
265+
multichallenge.stream().filter(c -> TOKEN_TYPE_WEBAUTHN.equals(c.getType())).collect(Collectors.toList()).forEach(c -> {
266+
if (c instanceof WebAuthn) {
267+
ret.add((WebAuthn) c);
268+
}
269+
});
270+
return ret;
271+
}
272+
214273
/**
215274
* @return the transaction id that was triggered or an empty string if nothing was triggered
216275
*/
@@ -265,7 +324,7 @@ public String getType() {
265324
return type;
266325
}
267326

268-
public int getOTPlength() {
327+
public int getOTPLength() {
269328
return otplen;
270329
}
271330

0 commit comments

Comments
 (0)