diff --git a/forgerock-auth/src/main/java/org/forgerock/android/auth/ServerConfig.java b/forgerock-auth/src/main/java/org/forgerock/android/auth/ServerConfig.java index 4f7f2cab..99cf04be 100644 --- a/forgerock-auth/src/main/java/org/forgerock/android/auth/ServerConfig.java +++ b/forgerock-auth/src/main/java/org/forgerock/android/auth/ServerConfig.java @@ -71,7 +71,7 @@ private ServerConfig(@NonNull Context context, getTimeOut(context, timeout), timeUnit, cookieJarSupplier, getPins(context, pins), - () -> singletonList(new OkHttpRequestInterceptor()), + () -> Arrays.asList(new OkHttpRequestInterceptor(), new OkHttpResponseInterceptor()), buildSteps); this.url = url; this.realm = realm == null ? context.getResources().getString(R.string.forgerock_realm) : realm; diff --git a/forgerock-core/src/main/java/org/forgerock/android/auth/FRResponseInterceptor.java b/forgerock-core/src/main/java/org/forgerock/android/auth/FRResponseInterceptor.java new file mode 100644 index 00000000..0f475189 --- /dev/null +++ b/forgerock-core/src/main/java/org/forgerock/android/auth/FRResponseInterceptor.java @@ -0,0 +1,30 @@ +/* + * This is WestJet source code and is for consideration as a pull request to ForgeRock. + * + * This fork was necessary to integrate with the F5® Distributed Cloud Defense Mobile SDK, + * which protects API endpoints from automation attacks by collecting telemetry and adding + * custom HTTP headers to requests. The response handling capability was built into the + * ForgeRock SDK to ensure that the F5 Distributed Cloud Bot Defense Mobile SDK can inspect + * and process response headers for its internal functionality. + * + * Dated: 2024 + */ + +package org.forgerock.android.auth; + +import androidx.annotation.NonNull; + +/** + * Observes and modifies incoming responses from the SDK. + * Interceptors can be used to add, remove, or transform headers, status codes, etc., on the response. + */ +public interface FRResponseInterceptor extends ResponseInterceptor { + /** + * Intercepts incoming responses from the SDK. + * + * @param response The original incoming response. + * @return The updated response. + */ + @NonNull + Response intercept(@NonNull Response response); +} \ No newline at end of file diff --git a/forgerock-core/src/main/java/org/forgerock/android/auth/OkHttpResponseInterceptor.java b/forgerock-core/src/main/java/org/forgerock/android/auth/OkHttpResponseInterceptor.java new file mode 100644 index 00000000..bc8696fa --- /dev/null +++ b/forgerock-core/src/main/java/org/forgerock/android/auth/OkHttpResponseInterceptor.java @@ -0,0 +1,44 @@ +/* + * This is WestJet source code and is for consideration as a pull request to ForgeRock. + * + * This fork was necessary to integrate with the F5® Distributed Cloud Defense Mobile SDK, + * which protects API endpoints from automation attacks by collecting telemetry and adding + * custom HTTP headers to requests. The response handling capability was built into the + * ForgeRock SDK to ensure that the F5 Distributed Cloud Bot Defense Mobile SDK can inspect + * and process response headers for its internal functionality. + * + * Dated: 2024 + */ + +package org.forgerock.android.auth; + +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Response; + +/** + * Interceptor to intercept Http Response and invoke registered {@link ResponseInterceptor} + */ +class OkHttpResponseInterceptor implements Interceptor { + + @NotNull + @Override + public Response intercept(@NotNull Chain chain) throws IOException { + Response response = chain.proceed(chain.request()); + + // Wrap the okhttp3.Response with the custom Response class + org.forgerock.android.auth.Response customResponse = new org.forgerock.android.auth.Response(response); + + ResponseInterceptor[] interceptors = ResponseInterceptorRegistry.getInstance().getResponseInterceptors(); + if (interceptors != null) { + for (ResponseInterceptor i : interceptors) { + customResponse = i.intercept(customResponse); + } + } + + return customResponse.getInternalRes(); + } +} \ No newline at end of file diff --git a/forgerock-core/src/main/java/org/forgerock/android/auth/Response.java b/forgerock-core/src/main/java/org/forgerock/android/auth/Response.java new file mode 100644 index 00000000..5649a534 --- /dev/null +++ b/forgerock-core/src/main/java/org/forgerock/android/auth/Response.java @@ -0,0 +1,64 @@ +/* + * This is WestJet source code and is for consideration as a pull request to ForgeRock. + * + * This fork was necessary to integrate with the F5® Distributed Cloud Defense Mobile SDK, + * which protects API endpoints from automation attacks by collecting telemetry and adding + * custom HTTP headers to requests. The response handling capability was built into the + * ForgeRock SDK to ensure that the F5 Distributed Cloud Bot Defense Mobile SDK can inspect + * and process response headers for its internal functionality. + * + * Dated: 2024 + */ + +package org.forgerock.android.auth; + +import androidx.annotation.NonNull; + +import java.net.URL; +import java.util.Iterator; +import java.util.List; + +import kotlin.Pair; +import lombok.AccessLevel; +import lombok.Getter; + +/** + * Represent an HTTP response. Instances of this class are immutable. + */ +public class Response { + + @Getter(AccessLevel.PACKAGE) + private okhttp3.Response internalRes; + + Response(@NonNull okhttp3.Response response) { + this.internalRes = response; + } + + public URL url() { + return internalRes.request().url().url(); + } + + public int code() { + return internalRes.code(); + } + + public String message() { + return internalRes.message(); + } + + public Iterator> headers() { + return internalRes.headers().iterator(); + } + + public String header(String name) { + return internalRes.header(name); + } + + public List headers(String name) { + return internalRes.headers(name); + } + + public okhttp3.ResponseBody body() { + return internalRes.body(); + } +} \ No newline at end of file diff --git a/forgerock-core/src/main/java/org/forgerock/android/auth/ResponseInterceptor.java b/forgerock-core/src/main/java/org/forgerock/android/auth/ResponseInterceptor.java new file mode 100644 index 00000000..01e115ac --- /dev/null +++ b/forgerock-core/src/main/java/org/forgerock/android/auth/ResponseInterceptor.java @@ -0,0 +1,31 @@ +/* + * This is WestJet source code and is for consideration as a pull request to ForgeRock. + * + * This fork was necessary to integrate with the F5® Distributed Cloud Defense Mobile SDK, + * which protects API endpoints from automation attacks by collecting telemetry and adding + * custom HTTP headers to requests. The response handling capability was built into the + * ForgeRock SDK to ensure that the F5 Distributed Cloud Bot Defense Mobile SDK can inspect + * and process response headers for its internal functionality. + * + * Dated: 2024 + */ + +package org.forgerock.android.auth; + +import androidx.annotation.NonNull; + +/** + * Observes and modifies incoming responses from the SDK. + * Interceptors can be used to add, remove, or transform headers, status codes, etc., on the response. + */ +public interface ResponseInterceptor { + + /** + * Intercept and modify the response. + * + * @param response The original response. + * @return The modified response. + */ + @NonNull + Response intercept(@NonNull Response response); +} \ No newline at end of file diff --git a/forgerock-core/src/main/java/org/forgerock/android/auth/ResponseInterceptorRegistry.java b/forgerock-core/src/main/java/org/forgerock/android/auth/ResponseInterceptorRegistry.java new file mode 100644 index 00000000..ea99b75d --- /dev/null +++ b/forgerock-core/src/main/java/org/forgerock/android/auth/ResponseInterceptorRegistry.java @@ -0,0 +1,48 @@ +/* + * This is WestJet source code and is for consideration as a pull request to ForgeRock. + * + * This fork was necessary to integrate with the F5® Distributed Cloud Defense Mobile SDK, + * which protects API endpoints from automation attacks by collecting telemetry and adding + * custom HTTP headers to requests. The response handling capability was built into the + * ForgeRock SDK to ensure that the F5 Distributed Cloud Bot Defense Mobile SDK can inspect + * and process response headers for its internal functionality. + * + * Dated: 2024 + */ + +package org.forgerock.android.auth; + +/** + * Registry to manage {@link ResponseInterceptor} + */ +public class ResponseInterceptorRegistry { + + private static final ResponseInterceptorRegistry INSTANCE = new ResponseInterceptorRegistry(); + + private ResponseInterceptor[] responseInterceptors; + + private ResponseInterceptorRegistry() { + } + + /** + * Returns a cached instance {@link ResponseInterceptorRegistry} + * + * @return instance of {@link ResponseInterceptorRegistry} + */ + public static ResponseInterceptorRegistry getInstance() { + return INSTANCE; + } + + /** + * Register new {@link ResponseInterceptor}(s) + * + * @param responseInterceptors A list of response interceptors + */ + public void register(ResponseInterceptor... responseInterceptors) { + this.responseInterceptors = responseInterceptors; + } + + public ResponseInterceptor[] getResponseInterceptors() { + return this.responseInterceptors; + } +} \ No newline at end of file