Skip to content

Commit 2f2c390

Browse files
47 implement token enrollment via validatecheck (#51)
* Update challenge and consts with image * implement imgs * Update the tests * Update WebAuthn.java * Update PIResponse.java * Make possible to get the challenge's image * Update TestWebAuthn.java * Update TestU2F.java * Update tests
1 parent ed7d053 commit 2f2c390

7 files changed

Lines changed: 134 additions & 14 deletions

File tree

src/main/java/org/privacyidea/Challenge.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public String getMessage()
5151
return message;
5252
}
5353

54-
public String getImage() { return image; }
54+
public String getImage() { return image.replaceAll("\"", ""); }
5555

5656
public String getTransactionID()
5757
{

src/main/java/org/privacyidea/JSONParser.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import static org.privacyidea.PIConstants.ERROR;
2525
import static org.privacyidea.PIConstants.ID;
2626
import static org.privacyidea.PIConstants.IMAGE;
27+
import static org.privacyidea.PIConstants.IMG;
2728
import static org.privacyidea.PIConstants.INFO;
2829
import static org.privacyidea.PIConstants.JSONRPC;
2930
import static org.privacyidea.PIConstants.MAXFAIL;
@@ -213,18 +214,18 @@ public PIResponse parsePIResponse(String serverResponse)
213214
.getAsJsonObject();
214215
String serial = getString(challenge, SERIAL);
215216
String message = getString(challenge, MESSAGE);
216-
String image = getString(challenge, IMAGE);
217+
String image = getItemFromAttributes(IMG, challenge).replaceAll("\"", "");
217218
String transactionid = getString(challenge, TRANSACTION_ID);
218219
String type = getString(challenge, TYPE);
219220

220221
if (TOKEN_TYPE_WEBAUTHN.equals(type))
221222
{
222-
String webAuthnSignRequest = getSignRequestFromAttributes(WEBAUTHN_SIGN_REQUEST, challenge);
223+
String webAuthnSignRequest = getItemFromAttributes(WEBAUTHN_SIGN_REQUEST, challenge);
223224
response.multichallenge.add(new WebAuthn(serial, message, image, transactionid, webAuthnSignRequest));
224225
}
225226
else if (TOKEN_TYPE_U2F.equals(type))
226227
{
227-
String u2fSignRequest = getSignRequestFromAttributes(U2F_SIGN_REQUEST, challenge);
228+
String u2fSignRequest = getItemFromAttributes(U2F_SIGN_REQUEST, challenge);
228229
response.multichallenge.add(new U2F(serial, message, image, transactionid, u2fSignRequest));
229230
}
230231
else
@@ -257,14 +258,14 @@ static String mergeWebAuthnSignRequest(WebAuthn webAuthn, List<String> arr) thro
257258
return signRequest.toString();
258259
}
259260

260-
private String getSignRequestFromAttributes(String requestType, JsonObject jsonObject)
261+
private String getItemFromAttributes(String item, JsonObject jsonObject)
261262
{
262263
String ret = "";
263264
JsonElement attributeElement = jsonObject.get(ATTRIBUTES);
264265
if (attributeElement != null && !attributeElement.isJsonNull())
265266
{
266267
JsonElement requestElement = attributeElement.getAsJsonObject()
267-
.get(requestType);
268+
.get(item);
268269
if (requestElement != null && !requestElement.isJsonNull())
269270
{
270271
ret = requestElement.toString();

src/main/java/org/privacyidea/PIConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ private PIConstants()
6565
public static final String PREFERRED_CLIENT_MODE = "preferred_client_mode";
6666
public static final String MESSAGE = "message";
6767
public static final String IMAGE = "image";
68+
public static final String IMG = "img";
6869
public static final String MESSAGES = "messages";
6970
public static final String MULTI_CHALLENGE = "multi_challenge";
7071
public static final String ATTRIBUTES = "attributes";

src/test/java/org/privacyidea/TestU2F.java

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,19 @@ public void testTriggerU2F()
104104
Optional<Challenge> opt = response.multiChallenge().stream()
105105
.filter(challenge -> TOKEN_TYPE_U2F.equals(challenge.getType()))
106106
.findFirst();
107-
Challenge a = opt.get();
108-
if (a instanceof U2F)
107+
if (opt.isPresent())
109108
{
110-
U2F b = (U2F) a;
111-
String trimmedRequest = u2fSignRequest.replaceAll("\n", "").replaceAll(" ", "");
112-
assertEquals(trimmedRequest, b.signRequest());
109+
Challenge a = opt.get();
110+
if (a instanceof U2F)
111+
{
112+
U2F b = (U2F) a;
113+
String trimmedRequest = u2fSignRequest.replaceAll("\n", "").replaceAll(" ", "");
114+
assertEquals(trimmedRequest, b.signRequest());
115+
}
116+
else
117+
{
118+
fail();
119+
}
113120
}
114121
else
115122
{
@@ -155,4 +162,41 @@ public void testSuccess()
155162
assertTrue(response.status);
156163
assertTrue(response.value);
157164
}
165+
166+
@Test
167+
public void testSuccessWithoutHeader()
168+
{
169+
String username = "Test";
170+
171+
String responseBody =
172+
"{\n" + " \"detail\": {\n" + " \"message\": \"matching 1 tokens\",\n" + " \"otplen\": 6,\n" +
173+
" \"serial\": \"PISP0001C673\",\n" + " \"threadid\": 140536383567616,\n" +
174+
" \"type\": \"totp\"\n" + " },\n" + " \"id\": 1,\n" + " \"jsonrpc\": \"2.0\",\n" +
175+
" \"result\": {\n" + " \"status\": true,\n" + " \"value\": true\n" + " },\n" +
176+
" \"time\": 1589276995.4397042,\n" + " \"version\": \"privacyIDEA 3.2.1\",\n" +
177+
" \"versionnumber\": \"3.2.1\",\n" + " \"signature\": \"rsa_sha256_pss:AAAAAAAAAAA\"\n" + "}";
178+
179+
mockServer.when(HttpRequest.request().withPath(PIConstants.ENDPOINT_VALIDATE_CHECK).withMethod("POST").withBody(
180+
"user=Test&transaction_id=16786665691788289392&pass=" +
181+
"&clientdata=eyJjaGFsbGVuZ2UiOiJpY2UBc3NlcnRpb24ifQ" +
182+
"&signaturedata=AQAAAxAwRQIgZwEObruoCRRo738F9up1tdV2M0H1MdP5pkO5Eg"))
183+
.respond(HttpResponse.response().withBody(responseBody));
184+
185+
String u2fSignResponse = "{\"clientData\":\"eyJjaGFsbGVuZ2UiOiJpY2UBc3NlcnRpb24ifQ\"," + "\"errorCode\":0," +
186+
"\"keyHandle\":\"UUHmZ4BUFCrt7q88MhlQkjlZqzZW1lC-jDdFd2pKDUsNnA\"," +
187+
"\"signatureData\":\"AQAAAxAwRQIgZwEObruoCRRo738F9up1tdV2M0H1MdP5pkO5Eg\"}";
188+
189+
PIResponse response = privacyIDEA.validateCheckU2F(username, "16786665691788289392", u2fSignResponse);
190+
191+
assertEquals(1, response.id);
192+
assertEquals("matching 1 tokens", response.message);
193+
assertEquals(6, response.otpLength);
194+
assertEquals("PISP0001C673", response.serial);
195+
assertEquals("totp", response.type);
196+
assertEquals("2.0", response.jsonRPCVersion);
197+
assertEquals("3.2.1", response.piVersion);
198+
assertEquals("rsa_sha256_pss:AAAAAAAAAAA", response.signature);
199+
assertTrue(response.status);
200+
assertTrue(response.value);
201+
}
158202
}

src/test/java/org/privacyidea/TestValidateCheck.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.privacyidea;
1717

18+
import java.util.HashMap;
19+
import java.util.Map;
1820
import java.util.concurrent.TimeUnit;
1921
import org.junit.After;
2022
import org.junit.Before;
@@ -80,6 +82,42 @@ public void testOTPSuccess()
8082
assertTrue(response.value);
8183
}
8284

85+
@Test
86+
public void testOTPAddHeader()
87+
{
88+
String responseBody =
89+
"{\n" + " \"detail\": {\n" + " \"message\": \"matching 1 tokens\",\n" + " \"otplen\": 6,\n" +
90+
" \"serial\": \"PISP0001C673\",\n" + " \"threadid\": 140536383567616,\n" +
91+
" \"type\": \"totp\"\n" + " },\n" + " \"id\": 1,\n" + " \"jsonrpc\": \"2.0\",\n" +
92+
" \"result\": {\n" + " \"status\": true,\n" + " \"value\": true\n" + " },\n" +
93+
" \"time\": 1589276995.4397042,\n" + " \"version\": \"privacyIDEA 3.2.1\",\n" +
94+
" \"versionnumber\": \"3.2.1\",\n" + " \"signature\": \"rsa_sha256_pss:AAAAAAAAAAA\"\n" + "}";
95+
96+
mockServer.when(HttpRequest.request().withMethod("POST").withPath("/validate/check")
97+
.withBody("user=" + username + "&pass=" + otp)).respond(
98+
HttpResponse.response().withContentType(MediaType.APPLICATION_JSON).withBody(responseBody)
99+
.withDelay(TimeUnit.MILLISECONDS, 50));
100+
101+
Map<String, String> header = new HashMap<>();
102+
header.put("accept-language", "en");
103+
PIResponse response = privacyIDEA.validateCheck(username, otp, header);
104+
105+
assertEquals(1, response.id);
106+
assertEquals("matching 1 tokens", response.message);
107+
assertEquals(6, response.otpLength);
108+
assertEquals("PISP0001C673", response.serial);
109+
assertEquals("totp", response.type);
110+
assertEquals("2.0", response.jsonRPCVersion);
111+
assertEquals("3.2.1", response.piVersion);
112+
assertEquals("rsa_sha256_pss:AAAAAAAAAAA", response.signature);
113+
// Trim all whitespaces, newlines
114+
assertEquals(responseBody.replaceAll("[\n\r]", ""), response.rawMessage.replaceAll("[\n\r]", ""));
115+
assertEquals(responseBody.replaceAll("[\n\r]", ""), response.toString().replaceAll("[\n\r]", ""));
116+
// result
117+
assertTrue(response.status);
118+
assertTrue(response.value);
119+
}
120+
83121
@Test
84122
public void testLostValues()
85123
{

src/test/java/org/privacyidea/TestValidateCheckSerial.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,40 @@ public void testNoChallengeResponsePINPlusOTP()
5757
String serial = "TOTP0001AFB9";
5858
String pinPlusOTP = "123456";
5959

60-
PIResponse response = privacyIDEA.validateCheckSerial(serial, pinPlusOTP, Collections.emptyMap());
60+
PIResponse response = privacyIDEA.validateCheckSerial(serial, pinPlusOTP);
61+
62+
assertEquals(responseBody, response.toString());
63+
assertEquals("matching1tokens", response.message);
64+
assertEquals(6, response.otpLength);
65+
assertEquals("TOTP0001AFB9", response.serial);
66+
assertEquals("totp", response.type);
67+
assertEquals(1, response.id);
68+
assertEquals("2.0", response.jsonRPCVersion);
69+
assertTrue(response.status);
70+
assertTrue(response.value);
71+
assertEquals("3.6.3", response.piVersion);
72+
assertEquals("rsa_sha256_pss:913056e002a...103456d32cca0222e5d", response.signature);
73+
}
74+
75+
@Test
76+
public void testNoChallengeResponseTransactionID()
77+
{
78+
String responseBody = "{\"detail\":{" + "\"message\":\"matching1tokens\"," + "\"otplen\":6," +
79+
"\"serial\":\"TOTP0001AFB9\"," + "\"threadid\":140050919388928," + "\"type\":\"totp\"}," +
80+
"\"id\":1," + "\"jsonrpc\":\"2.0\"," + "\"result\":{" + "\"status\":true," +
81+
"\"value\":true}," + "\"time\":1649684011.250808," + "\"version\":\"privacyIDEA3.6.3\"," +
82+
"\"versionnumber\":\"3.6.3\"," +
83+
"\"signature\":\"rsa_sha256_pss:913056e002a...103456d32cca0222e5d\"}";
84+
85+
mockServer.when(HttpRequest.request().withPath(PIConstants.ENDPOINT_VALIDATE_CHECK).withMethod("POST")
86+
.withBody("serial=TOTP0001AFB9&pass=123456&transaction_id=12093809214"))
87+
.respond(HttpResponse.response().withBody(responseBody));
88+
89+
String serial = "TOTP0001AFB9";
90+
String pinPlusOTP = "123456";
91+
String transactionID = "12093809214";
92+
93+
PIResponse response = privacyIDEA.validateCheckSerial(serial, pinPlusOTP, transactionID);
6194

6295
assertEquals(responseBody, response.toString());
6396
assertEquals("matching1tokens", response.message);

src/test/java/org/privacyidea/TestWebAuthn.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ public void testSuccess()
5757
String webauthnSignResponse = "{" + "\"credentialid\":\"X9FrwMfmzj...saw21\"," +
5858
"\"authenticatordata\":\"xGzvgq0bVGR3WR0A...ZJdA7cBAAAACA\"," +
5959
"\"clientdata\":\"eyJjaGFsbG...dfhs\"," +
60-
"\"signaturedata\":\"MEUCIQDNrG...43hc\"}";
60+
"\"signaturedata\":\"MEUCIQDNrG...43hc\"," +
61+
"\"assertionclientextensions\":\"alsjdlfkjsadjeiw\"," +
62+
"\"userhandle\":\"jalsdkjflsjfuhuweuvccco2\"\n" + "}";
6163

6264
String responseBody =
6365
"{\n" + " \"detail\": {\n" + " \"message\": \"matching 1 tokens\",\n" + " \"otplen\": 6,\n" +
@@ -68,7 +70,7 @@ public void testSuccess()
6870
" \"versionnumber\": \"3.2.1\",\n" + " \"signature\": \"rsa_sha256_pss:AAAAAAAAAAA\"\n" + "}";
6971

7072
mockServer.when(HttpRequest.request().withPath(PIConstants.ENDPOINT_VALIDATE_CHECK).withMethod("POST").withBody(
71-
"user=Test&transaction_id=16786665691788289392&pass=&credentialid=X9FrwMfmzj...saw21&clientdata=eyJjaGFsbG...dfhs&signaturedata=MEUCIQDNrG...43hc&authenticatordata=xGzvgq0bVGR3WR0A...ZJdA7cBAAAACA"))
73+
"user=Test&transaction_id=16786665691788289392&pass=&credentialid=X9FrwMfmzj...saw21&clientdata=eyJjaGFsbG...dfhs&signaturedata=MEUCIQDNrG...43hc&authenticatordata=xGzvgq0bVGR3WR0A...ZJdA7cBAAAACA&userhandle=jalsdkjflsjfuhuweuvccco2&assertionclientextensions=alsjdlfkjsadjeiw"))
7274
.respond(HttpResponse.response().withBody(responseBody));
7375

7476
PIResponse response = privacyIDEA.validateCheckWebAuthn("Test", "16786665691788289392", webauthnSignResponse,
@@ -149,6 +151,7 @@ public void testTriggerWebAuthn()
149151
WebAuthn b = (WebAuthn) a;
150152
String trimmedRequest = webauthnrequest.replaceAll("\n", "").replaceAll(" ", "");
151153
assertEquals(trimmedRequest, b.signRequest());
154+
assertEquals("static/img/FIDO-U2F-Security-Key-444x444.png", b.getImage());
152155
}
153156
else
154157
{

0 commit comments

Comments
 (0)