diff --git a/README.md b/README.md
index 70bf0b8..4d436cc 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ Go to your project's pom.xml file and add as dependency.
com.liveperson.faas
functions-client
- 1.1.6
+ 1.2.2
```
@@ -145,7 +145,7 @@ optionalParams.setRequestId("requestId");
### Fetching lambdas
-**You have to use your own authentication method when fetching lambdas as it still relies on OAuth 1.0.**
+**You have to use your own authentication method when fetching lambdas as it relies on OAuth 1.0. / Oauth 2.0 + DPoP**
Fetching lambdas of account
diff --git a/src/test/java/com/liveperson/faas/client/FaaSClientTest.java b/src/test/java/com/liveperson/faas/client/FaaSClientTest.java
index 3a54b25..88eb8cd 100644
--- a/src/test/java/com/liveperson/faas/client/FaaSClientTest.java
+++ b/src/test/java/com/liveperson/faas/client/FaaSClientTest.java
@@ -11,6 +11,7 @@
import com.liveperson.faas.http.RestClient;
import com.liveperson.faas.metriccollector.MetricCollector;
import com.liveperson.faas.response.lambda.LambdaResponse;
+import com.liveperson.faas.security.AuthDpopSignatureBuilder;
import com.liveperson.faas.security.AuthSignatureBuilder;
import com.liveperson.faas.util.EventResponse;
import com.liveperson.faas.util.UUIDResponse;
@@ -31,12 +32,15 @@
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyFloat;
+import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyMap;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
@@ -46,6 +50,8 @@ public class FaaSClientTest {
private final SimpleDateFormat mockDateFormat = new SimpleDateFormat("yyyy-MM-dd");
@InjectMocks
private FaaSWebClient client;
+ @InjectMocks
+ private FaaSWebClient clientWithDPoP;
@Mock
private RestClient restClientMock;
@Mock
@@ -60,6 +66,8 @@ public class FaaSClientTest {
@Mock
private AuthSignatureBuilder authSignatureBuilder;
@Mock
+ private AuthDpopSignatureBuilder authDPoPSignatureBuilder;
+ @Mock
private MetricCollector metricCollectorMock;
@Mock
private DefaultIsImplementedCache defaultIsImplementedCacheMock;
@@ -73,12 +81,16 @@ public class FaaSClientTest {
private String faasUIUrl = "faasUI.com";
private String requestId = "requestId";
private int defaultTimeOut = 15000;
+ // Oauth2 + DPOP
+ private String accessToken = "some_access_token";
+ private String dpopHeader = "dpopJWT";
private OptionalParams optionalParams;
@Before
public void before() throws Exception {
client = getFaaSClient();
+ clientWithDPoP = getFaaSClientWithDpopAuth();
optionalParams = new OptionalParams();
mockDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
optionalParams.setTimeOutInMs(defaultTimeOut);
@@ -86,6 +98,9 @@ public void before() throws Exception {
when(csdsClientMock.getDomain(eq(FaaSWebClient.CSDS_GW_SERVICE_NAME))).thenReturn(faasGWUrl);
when(csdsClientMock.getDomain(eq(FaaSWebClient.CSDS_UI_SERVICE_NAME))).thenReturn(faasUIUrl);
when(authSignatureBuilder.getAuthHeader()).thenReturn(authHeader);
+ // Oauth2 + DPoP
+ when(authDPoPSignatureBuilder.getAccessTokenInternal(anyString())).thenReturn(accessToken);
+ when(authDPoPSignatureBuilder.getDpopHeaderInternal(anyString(), anyString(), anyString())).thenReturn(dpopHeader);
}
@Test
@@ -111,7 +126,28 @@ public void invokeViaUUIDWithRequestId() throws Exception {
"X-REQUEST-ID").contains(requestId));
assertEquals("Lambda invocation result does not match expected value",
"lambda_result", response);
+ }
+
+ @Test
+ public void invokeViaUUIDWithDPoP() throws Exception {
+ String payload = "request_data";
+ long timestamp = System.currentTimeMillis();
+ FaaSInvocation invocationData = new FaaSInvocation(null, payload);
+ invocationData.setTimestamp(timestamp);
+ when(restClientMock.post(eq(getExpectedInvokeUUIDUrl()), httpHeaderCaptor.capture(),
+ httpBodyCaptor.capture(), eq(defaultTimeOut))).thenReturn("\"lambda_result\"");
+ String response = clientWithDPoP.invokeByUUID(externalSystem, lambdaUUID, invocationData, String.class, optionalParams
+ );
+
+ verify(metricCollectorMock, times(1)).onInvokeByUUIDSuccess(eq(externalSystem), anyFloat(), eq(lambdaUUID),
+ eq(accountId));
+ assertEquals("Lambda invocation with the wrong body",
+ getExpectedRequestBody(timestamp, "[]", "\"request_data\""), httpBodyCaptor.getValue());
+ assertTrue("Lambda invocation with wrong authorization header", httpHeaderCaptor.getValue().get("Authorization").equals("DPoP " + accessToken));
+ assertTrue("Lambda invocation with wrong DPoP header", httpHeaderCaptor.getValue().get("DPoP").equals(dpopHeader));
+ assertEquals("Lambda invocation result does not match expected value",
+ "lambda_result", response);
}
@Test
@@ -284,6 +320,45 @@ public void invokeViaEventType() throws Exception {
response[0].toString());
}
+
+ @Test
+ public void invokeViaEventTypeWithAuthDPoP() throws Exception {
+ UUIDResponse payload = new UUIDResponse();
+ payload.key = "requestKey";
+ payload.value = "requestValue";
+ long timestamp = System.currentTimeMillis();
+ String mockResponse = "[\n" +
+ " {\n" +
+ " \"uuid\": \"" + lambdaUUID + "\",\n" +
+ " \"timestamp\": \"2017-07-09\",\n" +
+ " \"result\": {\n" +
+ " \"key\": \"responseKey\",\n" +
+ " \"value\": \"responseValue\"\n" +
+ " }\n" +
+ " }\n" +
+ "]";
+ Map headers = getTestHeaders();
+ FaaSInvocation invocationData = getUUIDResponseFaaSInvocation(payload, timestamp, headers);
+ EventResponse expectedResponse = getExpectedResponse();
+
+ when(restClientMock.post(eq(getExpectedInvokeEventUrl()), httpHeaderCaptor.capture(),
+ httpBodyCaptor.capture(), eq(defaultTimeOut))).thenReturn(mockResponse);
+ EventResponse[] response = clientWithDPoP.invokeByEvent(externalSystem,
+ FaaSEvent.ChatPostSurveyEmailTranscript,
+ invocationData, EventResponse[].class, optionalParams);
+
+ verify(metricCollectorMock, times(1)).onInvokeByEventSuccess(eq(externalSystem), anyInt(), eq(event.toString()),
+ eq(accountId));
+ assertEquals("Lambda invocation with the wrong body",
+ getExpectedRequestBody(timestamp, "[{\"key\":\"testHeader\",\"value\":\"testHeaderValue\"}]", "{\"key" +
+ "\":\"requestKey\",\"value\":\"requestValue\"}"),
+ httpBodyCaptor.getValue());
+ assertTrue("Lambda invocation with wrong authorization header", httpHeaderCaptor.getValue().get("Authorization").equals("DPoP " + accessToken));
+ assertTrue("Lambda invocation with wrong DPoP header", httpHeaderCaptor.getValue().get("DPoP").equals(dpopHeader));
+ assertEquals("Lambda invocation result does not match expected value", expectedResponse.toString(),
+ response[0].toString());
+ }
+
@Test
public void invokeViaEventTypeWithEventString() throws Exception {
UUIDResponse payload = new UUIDResponse();
@@ -582,6 +657,23 @@ public void getLambdas() throws Exception {
assertEquals(expectedResponse.get(0), actualResponse.get(0));
}
+ @Test
+ public void getLambdasWithAuthDPoP() throws Exception {
+ String mockResponse = getMockResponse();
+
+ when(restClientMock.get(eq(getExpectedLambdasOfAnAccountUrl()), httpHeaderCaptor.capture(), eq(defaultTimeOut)))
+ .thenReturn(mockResponse);
+ List actualResponse = clientWithDPoP.getLambdas(userId, new HashMap(), optionalParams);
+ List expectedResponse = objectMapper.readValue(mockResponse,
+ new TypeReference>() {
+ });
+
+ verify(metricCollectorMock, times(1)).onGetLambdasSuccess(eq(userId), anyFloat(), eq(accountId));
+ assertTrue("Lambda invocation with wrong authorization header", httpHeaderCaptor.getValue().get("Authorization").equals("DPoP " + accessToken));
+ assertTrue("Lambda invocation with wrong DPoP header", httpHeaderCaptor.getValue().get("DPoP").equals(dpopHeader));
+ assertEquals(expectedResponse.get(0), actualResponse.get(0));
+ }
+
@Test
public void getLambdasWithOptionalQueryParameters() throws IOException {
Map headers = getHeaders();
@@ -710,6 +802,15 @@ private FaaSWebClient getFaaSClient() {
.build();
}
+ private FaaSWebClient getFaaSClientWithDpopAuth() {
+ return new FaaSWebClient.Builder(accountId).withCsdsClient(csdsClientMock)
+ .withRestClient(restClientMock)
+ .withAuthDPoPSignatureBuilder(this.authDPoPSignatureBuilder)
+ .withMetricCollector(metricCollectorMock)
+ .withIsImplementedCache(defaultIsImplementedCacheMock)
+ .build();
+ }
+
private Map getHeaders() {
Map headers = new HashMap<>();
headers.put("Authorization", authHeader);
diff --git a/src/test/java/com/liveperson/faas/client/FaaSClientWithDpopAuthTest.java b/src/test/java/com/liveperson/faas/client/FaaSClientWithDpopAuthTest.java
deleted file mode 100644
index fb0cac8..0000000
--- a/src/test/java/com/liveperson/faas/client/FaaSClientWithDpopAuthTest.java
+++ /dev/null
@@ -1,853 +0,0 @@
-package com.liveperson.faas.client;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.liveperson.faas.client.types.FaaSEventImplementedExpiry;
-import com.liveperson.faas.client.types.OptionalParams;
-import com.liveperson.faas.csds.CsdsClient;
-import com.liveperson.faas.dto.FaaSError;
-import com.liveperson.faas.dto.FaaSInvocation;
-import com.liveperson.faas.exception.*;
-import com.liveperson.faas.http.RestClient;
-import com.liveperson.faas.metriccollector.MetricCollector;
-import com.liveperson.faas.response.lambda.LambdaResponse;
-import com.liveperson.faas.security.AuthDpopSignatureBuilder;
-import com.liveperson.faas.security.AuthSignatureBuilder;
-import com.liveperson.faas.util.EventResponse;
-import com.liveperson.faas.util.UUIDResponse;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-
-import java.io.IOException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.time.LocalDateTime;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyFloat;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyMap;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.*;
-
-@RunWith(MockitoJUnitRunner.class)
-public class FaaSClientWithDpopAuthTest {
-
- private final ObjectMapper objectMapper = new ObjectMapper();
- private final SimpleDateFormat mockDateFormat = new SimpleDateFormat("yyyy-MM-dd");
- @InjectMocks
- private FaaSWebClient client;
- @Mock
- private RestClient restClientMock;
- @Mock
- private CsdsClient csdsClientMock;
- @Captor
- private ArgumentCaptor