From 2d352e78a5ef35b4bf53fdaaaa3c1a6b0539c13c Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Tue, 28 Nov 2023 18:33:21 -0300 Subject: [PATCH] Internal authenticator --- .../client/network/OkHttpAuthenticator.java | 49 +++++++++ .../network/OkHttpAuthenticatorTest.java | 103 ++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 src/main/java/io/split/android/client/network/OkHttpAuthenticator.java create mode 100644 src/test/java/io/split/android/client/network/OkHttpAuthenticatorTest.java diff --git a/src/main/java/io/split/android/client/network/OkHttpAuthenticator.java b/src/main/java/io/split/android/client/network/OkHttpAuthenticator.java new file mode 100644 index 000000000..d28b5b01c --- /dev/null +++ b/src/main/java/io/split/android/client/network/OkHttpAuthenticator.java @@ -0,0 +1,49 @@ +package io.split.android.client.network; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.List; +import java.util.Map; + +import io.split.android.client.utils.logger.Logger; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.Route; + +class OkHttpAuthenticator implements okhttp3.Authenticator { + + private final SplitAuthenticator mSplitAuthenticator; + + OkHttpAuthenticator(SplitAuthenticator splitAuthenticator) { + mSplitAuthenticator = splitAuthenticator; + } + + @Nullable + @Override + public Request authenticate(@Nullable Route route, @NonNull Response response) { + + try { + SplitAuthenticatedRequest authenticatedRequestResult = mSplitAuthenticator.authenticate(new SplitAuthenticatedRequest(response)); + if (authenticatedRequestResult == null) { + return null; + } + + Request.Builder builder = response.request() + .newBuilder(); + + if (authenticatedRequestResult.getHeaders() != null) { + for (Map.Entry> header : authenticatedRequestResult.getHeaders().entrySet()) { + for (String value : header.getValue()) { + builder.addHeader(header.getKey(), value); + } + } + } + + return builder.build(); + } catch (Exception exception) { + Logger.e("Error authenticating request: ", exception.getMessage()); + return null; + } + } +} diff --git a/src/test/java/io/split/android/client/network/OkHttpAuthenticatorTest.java b/src/test/java/io/split/android/client/network/OkHttpAuthenticatorTest.java new file mode 100644 index 000000000..0c4211302 --- /dev/null +++ b/src/test/java/io/split/android/client/network/OkHttpAuthenticatorTest.java @@ -0,0 +1,103 @@ +package io.split.android.client.network; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.Collections; +import java.util.Objects; + +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.Route; + +public class OkHttpAuthenticatorTest { + + private OkHttpAuthenticator mAuthenticator; + private SplitAuthenticator mSplitAuthenticator; + + @Before + public void setUp() { + mSplitAuthenticator = mock(SplitAuthenticator.class); + mAuthenticator = new OkHttpAuthenticator(mSplitAuthenticator); + } + + @Test + public void callingAuthenticateCallsAuthenticateOnTheSplitAuthenticator() throws IOException { + mAuthenticator.authenticate(mock(Route.class), mock(Response.class)); + + verify(mSplitAuthenticator).authenticate(argThat(Objects::nonNull)); + } + + @Test + public void resultIsNullIfSplitAuthenticatorReturnsNull() throws IOException { + Request authenticate = mAuthenticator.authenticate(mock(Route.class), mock(Response.class)); + + assertNull(authenticate); + } + + @Test + public void headersFromAuthenticationAreNotAddedToResultWhenTheyAreNull() throws IOException { + Response mockResponse = mock(Response.class); + Request mockRequest = mock(Request.class); + Request.Builder mockBuilder = mock(Request.Builder.class); + Request mockResult = mock(Request.class); + + when(mockRequest.newBuilder()).thenReturn(mockBuilder); + when(mockResponse.request()).thenReturn(mockRequest); + when(mockBuilder.build()).thenReturn(mockResult); + + SplitAuthenticatedRequest mockAuthRequest = mock(SplitAuthenticatedRequest.class); + when(mockAuthRequest.getHeaders()).thenReturn(null); + when(mSplitAuthenticator.authenticate(any())).thenReturn(mockAuthRequest); + + Request result = mAuthenticator.authenticate(mock(Route.class), mockResponse); + + verify(mockRequest).newBuilder(); + verify(mockBuilder, times(0)).addHeader(any(), any()); + verify(mockBuilder).build(); + assertEquals(mockResult, result); + } + + @Test + public void exceptionInSplitAuthenticatorCausesResultToBeNull() throws IOException { + when(mSplitAuthenticator.authenticate(any())).thenThrow(new RuntimeException()); + + Request result = mAuthenticator.authenticate(mock(Route.class), mock(Response.class)); + + assertNull(result); + } + + @Test + public void authorizationHeadersAreAddedToResultRequest() { + Response mockResponse = mock(Response.class); + Request mockRequest = mock(Request.class); + Request.Builder mockBuilder = mock(Request.Builder.class); + Request mockResult = mock(Request.class); + + when(mockRequest.newBuilder()).thenReturn(mockBuilder); + when(mockResponse.request()).thenReturn(mockRequest); + when(mockBuilder.build()).thenReturn(mockResult); + + SplitAuthenticatedRequest mockAuthRequest = mock(SplitAuthenticatedRequest.class); + when(mockAuthRequest.getHeaders()).thenReturn(Collections.singletonMap("Authorization", Collections.singletonList("Bearer 1234567890"))); + when(mSplitAuthenticator.authenticate(any())).thenReturn(mockAuthRequest); + + Request result = mAuthenticator.authenticate(mock(Route.class), mockResponse); + + verify(mockRequest).newBuilder(); + verify(mockBuilder).addHeader("Authorization", "Bearer 1234567890"); + verify(mockBuilder).build(); + assertNotNull(result); + } +}