Skip to content
This repository was archived by the owner on Feb 13, 2024. It is now read-only.

Commit 5eecebf

Browse files
author
Philipp Etschel
committed
extended invitation parser so that it also can handle URI's which is very common in invitation redirects
Signed-off-by: Philipp Etschel <philipp.etschel@ch.bosch.com>
1 parent 6049854 commit 5eecebf

File tree

4 files changed

+75
-20
lines changed

4 files changed

+75
-20
lines changed

backend/business-partner-agent/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,12 @@
219219
<artifactId>mockito-junit-jupiter</artifactId>
220220
<scope>test</scope>
221221
</dependency>
222+
<dependency>
223+
<groupId>com.squareup.okhttp3</groupId>
224+
<artifactId>mockwebserver</artifactId>
225+
<version>4.9.3</version>
226+
<scope>test</scope>
227+
</dependency>
222228
</dependencies>
223229

224230
<build>

backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/InvitationParser.java

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,32 @@
3838
import org.hyperledger.bpa.controller.api.invitation.CheckInvitationResponse;
3939
import org.hyperledger.bpa.impl.util.Converter;
4040

41+
import java.net.URI;
42+
import java.net.URISyntaxException;
4143
import java.net.URLDecoder;
4244
import java.nio.charset.StandardCharsets;
4345
import java.util.Base64;
4446
import java.util.List;
4547
import java.util.Map;
4648

4749
@Slf4j
48-
@NoArgsConstructor
4950
@Singleton
5051
public class InvitationParser {
5152

52-
OkHttpClient httpClient = new OkHttpClient.Builder().followRedirects(false).build();
53+
private final OkHttpClient httpClient;
5354

54-
static List<String> CONNECTION_INVITATION_TYPES = List.of(
55+
private static final List<String> paramNames = List.of("c_i", "d_m", "oob");
56+
57+
static final List<String> CONNECTION_INVITATION_TYPES = List.of(
5558
"did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/invitation",
5659
"https://didcomm.org/connections/1.0/invitation");
57-
static List<String> OOB_INVITATION_TYPES = List.of("did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/out-of-band/1.0/invitation",
60+
static final List<String> OOB_INVITATION_TYPES = List.of("did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/out-of-band/1.0/invitation",
5861
"https://didcomm.org/out-of-band/1.0/invitation");
5962

63+
public InvitationParser() {
64+
this.httpClient = new OkHttpClient.Builder().followRedirects(false).build();
65+
}
66+
6067
@Inject
6168
@Setter(AccessLevel.PACKAGE)
6269
ObjectMapper mapper;
@@ -187,7 +194,6 @@ public Invitation parseInvitation(String invitationBlock) {
187194
}
188195

189196
private String parseInvitationBlock(@NonNull HttpUrl url) {
190-
List<String> paramNames = List.of("c_i", "d_m", "oob");
191197
for (String name : paramNames) {
192198
String invitationBlock = url.queryParameter(name);
193199
if (StringUtils.isNotEmpty(invitationBlock))
@@ -213,7 +219,7 @@ private String parseInvitationBlockFromRedirect(@NonNull HttpUrl url) {
213219
if (response.isRedirect()) {
214220
String location = response.header("location");
215221
if (StringUtils.isNotEmpty(location)) {
216-
HttpUrl locationUrl = HttpUrl.parse(location);
222+
HttpUrl locationUrl = getQueryFromLocation(location);
217223
if (locationUrl != null)
218224
return parseInvitationBlock(locationUrl);
219225
}
@@ -225,4 +231,25 @@ private String parseInvitationBlockFromRedirect(@NonNull HttpUrl url) {
225231
return null;
226232
}
227233

234+
/**
235+
* The location header can either be an HTTP URL or simply a URI, as we
236+
* only process the query, and we do not want to rewrite the query parser
237+
* the query is extracted from the URI and then wrapped again into a dummy HTTP URL
238+
* @param location the content of the location header
239+
* @return {@link HttpUrl} or null
240+
*/
241+
private HttpUrl getQueryFromLocation(String location) {
242+
HttpUrl result = null;
243+
try {
244+
URI uri = new URI(location);
245+
String query = uri.getQuery();
246+
if (StringUtils.isNotEmpty(query)) {
247+
result = HttpUrl.parse("https://placeholder.co?" + query);
248+
}
249+
} catch (URISyntaxException e) {
250+
log.error("Location header contained a invalid URI", e);
251+
}
252+
return result;
253+
}
254+
228255
}

backend/business-partner-agent/src/test/java/org/hyperledger/bpa/impl/InvitationParserTest.java

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,35 @@
1818
package org.hyperledger.bpa.impl;
1919

2020
import com.fasterxml.jackson.databind.ObjectMapper;
21+
import okhttp3.mockwebserver.MockResponse;
22+
import okhttp3.mockwebserver.MockWebServer;
23+
import org.hyperledger.bpa.controller.api.invitation.CheckInvitationResponse;
24+
import org.junit.jupiter.api.AfterEach;
2125
import org.junit.jupiter.api.Assertions;
26+
import org.junit.jupiter.api.BeforeEach;
2227
import org.junit.jupiter.api.Test;
2328

2429
public class InvitationParserTest {
2530

26-
@Test
27-
void TestParseReceiveInvitation() {
28-
InvitationParser p = new InvitationParser();
31+
public static MockWebServer mockWebServer;
32+
private InvitationParser p;
33+
34+
@BeforeEach
35+
void init() throws Exception {
36+
p = new InvitationParser();
2937
p.setMapper(new ObjectMapper());
3038

39+
mockWebServer = new MockWebServer();
40+
mockWebServer.start();
41+
}
42+
43+
@AfterEach
44+
void tearDown() throws Exception {
45+
mockWebServer.shutdown();
46+
}
47+
48+
@Test
49+
void TestParseReceiveInvitation() {
3150
InvitationParser.Invitation invitation = p.parseInvitation(this.invitation);
3251
Assertions.assertFalse(invitation.isOob());
3352
Assertions.assertTrue(invitation.isParsed());
@@ -36,9 +55,6 @@ void TestParseReceiveInvitation() {
3655

3756
@Test
3857
void TestParseReceiveOOBInvitation() {
39-
InvitationParser p = new InvitationParser();
40-
p.setMapper(new ObjectMapper());
41-
4258
InvitationParser.Invitation invitation = p.parseInvitation(oob);
4359
Assertions.assertTrue(invitation.isOob());
4460
Assertions.assertTrue(invitation.isParsed());
@@ -47,9 +63,6 @@ void TestParseReceiveOOBInvitation() {
4763

4864
@Test
4965
void TestParseReceiveDidCommInvitation() {
50-
InvitationParser p = new InvitationParser();
51-
p.setMapper(new ObjectMapper());
52-
5366
InvitationParser.Invitation invitation = p.parseInvitation(this.didCommInvitation);
5467
Assertions.assertFalse(invitation.isOob());
5568
Assertions.assertTrue(invitation.isParsed());
@@ -58,19 +71,28 @@ void TestParseReceiveDidCommInvitation() {
5871

5972
@Test
6073
void TestParseReceiveOOBDidCommInvitation() {
61-
InvitationParser p = new InvitationParser();
62-
p.setMapper(new ObjectMapper());
63-
6474
InvitationParser.Invitation invitation = p.parseInvitation(didCommOob);
6575
Assertions.assertTrue(invitation.isOob());
6676
Assertions.assertTrue(invitation.isParsed());
6777
Assertions.assertNotNull(invitation.getInvitation());
6878
}
6979

80+
@Test
81+
void testStreetcredURI() {
82+
MockResponse response = new MockResponse()
83+
.setResponseCode(301)
84+
.setHeader("location", streetCredRedirect);
85+
mockWebServer.enqueue(response);
86+
String httpUrl = mockWebServer.url("/46yG3VegpCqc").toString();
87+
CheckInvitationResponse parsed = p.checkInvitation(httpUrl);
88+
Assertions.assertEquals("Snapper", parsed.getLabel());
89+
}
90+
7091
private final String invitation = "ewogICAgIkB0eXBlIjogImRpZDpzb3Y6QnpDYnNOWWhNcmpIaXFaRFRVQVNIZztzcGVjL2Nvbm5lY3Rpb25zLzEuMC9pbnZpdGF0aW9uIiwKICAgICJAaWQiOiAiNGQ1OGJhZjktZDIwOS00MTE4LThkOTQtNGE0OTBlNGEwNGFhIiwKICAgICJzZXJ2aWNlRW5kcG9pbnQiOiAiaHR0cDovL2hvc3QuZG9ja2VyLmludGVybmFsOjgwMzAiLAogICAgInJlY2lwaWVudEtleXMiOiBbCiAgICAgICAgIjZCTlF1dFJIalNWNmJwQ0E2djVkRVB2NW12dWlRS2hyc256cEN4dUgzdXdqIgogICAgXSwKICAgICJsYWJlbCI6ICJCdXNpbmVzcyBQYXJ0bmVyIEFnZW50IDEiCn0=";
7192
private final String oob = "eyJAdHlwZSI6ICJkaWQ6c292OkJ6Q2JzTlloTXJqSGlxWkRUVUFTSGc7c3BlYy9vdXQtb2YtYmFuZC8xLjAvaW52aXRhdGlvbiIsICJAaWQiOiAiMmZhYmJhNzYtZTlhNy00Yzk4LTg2ZjMtMTFkNGE1MTYzYjQyIiwgImhhbmRzaGFrZV9wcm90b2NvbHMiOiBbImRpZDpzb3Y6QnpDYnNOWWhNcmpIaXFaRFRVQVNIZztzcGVjL2RpZGV4Y2hhbmdlLzEuMCJdLCAic2VydmljZXMiOiBbImRpZDpzb3Y6RXJhWUNESlVQc0NoYmt3N1MxdlY5NiJdLCAibGFiZWwiOiAiYm9iIn0=";
7293

7394
private final String didCommInvitation = "eyJAdHlwZSI6ICJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMC9pbnZpdGF0aW9uIiwgIkBpZCI6ICJkNGE5ZmY4YS1jNjlmLTRiMWQtODJlYi04NzQwYWRiMzE0MmEiLCAic2VydmljZUVuZHBvaW50IjogImh0dHBzOi8vaW52aXRlMS1icGEtYWNhcHktZGV2LmFwcHMuc2lsdmVyLmRldm9wcy5nb3YuYmMuY2EiLCAibGFiZWwiOiAiaW52aXRlMSIsICJyZWNpcGllbnRLZXlzIjogWyI5MnV2TTFFOG9RbXFUNGZLZkdtam5UTndiandqYUZXYVRpRmtMZXNvbnhSVCJdfQ==";
7495
private final String didCommOob = "eyJAdHlwZSI6ICJodHRwczovL2RpZGNvbW0ub3JnL291dC1vZi1iYW5kLzEuMC9pbnZpdGF0aW9uIiwgIkBpZCI6ICI2ZmYzY2UzNy1kYjM1LTRjYTctYTNkOS03MWJmNGYxYzhkYzQiLCAibGFiZWwiOiAiaW52aXRlMSIsICJzZXJ2aWNlcyI6IFsiZGlkOnNvdjpXc3FWaW4xWjRZdnZiODdzU1E3QzJtIl0sICJoYW5kc2hha2VfcHJvdG9jb2xzIjogWyJodHRwczovL2RpZGNvbW0ub3JnL2RpZGV4Y2hhbmdlLzEuMCJdfQ==";
7596

97+
private final String streetCredRedirect = "id.streetcred://launch/?d_m=eyJsYWJlbCI6IlNuYXBwZXIiLCJpbWFnZVVybCI6bnVsbCwic2VydmljZUVuZHBvaW50IjoiaHR0cHM6Ly90cmluc2ljLW1lZGlhdG9yLWFnZW50LWV1cm9wZS5henVyZXdlYnNpdGVzLm5ldC8iLCJyb3V0aW5nS2V5cyI6WyJDTFBmc3hVaDNMOWR2U2huNjRmYkZKZExrbzZHbmVhQkNEWkJQNjZpWVV3RCJdLCJyZWNpcGllbnRLZXlzIjpbIkc5cDVydVRqcDJiVHhWellIUVpySmZISkNDaENRVUpOVllrUWhTcGlmWTdkIl0sIkBpZCI6IjBiNTc1Zjc4LTNiNTQtNGFhNS1hMzMyLTcwNTljZDg5YzA1NiIsIkB0eXBlIjoiZGlkOnNvdjpCekNic05ZaE1yakhpcVpEVFVBU0hnO3NwZWMvY29ubmVjdGlvbnMvMS4wL2ludml0YXRpb24ifQ%3D%3D&orig=https%3a%2f%2fredir.trinsic.id%2f46yG3VegpCqc";
7698
}

backend/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
<mockito.version>4.1.0</mockito.version>
6464
<org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
6565
<pmd.version>6.41.0</pmd.version>
66-
<spotbugs.version>4.5.0</spotbugs.version>
66+
<spotbugs.version>4.5.1</spotbugs.version>
6767
<testcontainers.version>1.16.2</testcontainers.version>
6868
<!-- Plugin Versions -->
6969
<license-maven-plugin.version>4.1</license-maven-plugin.version>
@@ -264,7 +264,7 @@
264264
<plugin>
265265
<groupId>net.revelc.code.formatter</groupId>
266266
<artifactId>formatter-maven-plugin</artifactId>
267-
<version>2.17.0</version>
267+
<version>2.17.1</version>
268268
<executions>
269269
<execution>
270270
<goals>

0 commit comments

Comments
 (0)