diff --git a/malicious-site-protection/malicious-site-protection-impl/build.gradle b/malicious-site-protection/malicious-site-protection-impl/build.gradle index 98dfa2f669ba..7077945b75fa 100644 --- a/malicious-site-protection/malicious-site-protection-impl/build.gradle +++ b/malicious-site-protection/malicious-site-protection-impl/build.gradle @@ -33,6 +33,7 @@ if (localPropertiesFile.exists()) { dependencies { implementation project(":malicious-site-protection-api") + implementation project(':browser-api') anvil project(path: ':anvil-compiler') implementation project(path: ':anvil-annotations') diff --git a/malicious-site-protection/malicious-site-protection-impl/src/main/kotlin/com/duckduckgo/malicioussiteprotection/impl/data/network/MaliciousSiteProtectionRequestInterceptor.kt b/malicious-site-protection/malicious-site-protection-impl/src/main/kotlin/com/duckduckgo/malicioussiteprotection/impl/data/network/MaliciousSiteProtectionRequestInterceptor.kt new file mode 100644 index 000000000000..bfaa449e5b21 --- /dev/null +++ b/malicious-site-protection/malicious-site-protection-impl/src/main/kotlin/com/duckduckgo/malicioussiteprotection/impl/data/network/MaliciousSiteProtectionRequestInterceptor.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 DuckDuckGo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.duckduckgo.malicioussiteprotection.impl.data.network + +import com.duckduckgo.app.global.api.ApiInterceptorPlugin +import com.duckduckgo.di.scopes.AppScope +import com.duckduckgo.malicioussiteprotection.impl.BuildConfig +import com.squareup.anvil.annotations.ContributesMultibinding +import javax.inject.Inject +import logcat.logcat +import okhttp3.Interceptor +import okhttp3.Interceptor.Chain +import okhttp3.Response +import retrofit2.Invocation + +@ContributesMultibinding( + scope = AppScope::class, + boundType = ApiInterceptorPlugin::class, +) +class MaliciousSiteProtectionRequestInterceptor @Inject constructor() : ApiInterceptorPlugin, Interceptor { + override fun getInterceptor(): Interceptor = this + + override fun intercept(chain: Chain): Response { + val request = chain.request() + + val authRequired = chain.request().tag(Invocation::class.java) + ?.method() + ?.isAnnotationPresent(AuthRequired::class.java) == true + + return if (authRequired) { + val newRequest = chain.request().newBuilder() + newRequest.addHeader( + name = "X-Auth-Token", + value = BuildConfig.MALICIOUS_SITE_PROTECTION_AUTH_TOKEN, + ) + chain.proceed( + newRequest.build().also { logcat { "headers: ${it.headers}" } }, + ) + } else { + chain.proceed(request) + } + } +} diff --git a/malicious-site-protection/malicious-site-protection-impl/src/main/kotlin/com/duckduckgo/malicioussiteprotection/impl/data/network/MaliciousSiteService.kt b/malicious-site-protection/malicious-site-protection-impl/src/main/kotlin/com/duckduckgo/malicioussiteprotection/impl/data/network/MaliciousSiteService.kt index ba44b64ac2c2..b2c8c32d8a20 100644 --- a/malicious-site-protection/malicious-site-protection-impl/src/main/kotlin/com/duckduckgo/malicioussiteprotection/impl/data/network/MaliciousSiteService.kt +++ b/malicious-site-protection/malicious-site-protection-impl/src/main/kotlin/com/duckduckgo/malicioussiteprotection/impl/data/network/MaliciousSiteService.kt @@ -31,21 +31,27 @@ private const val MALWARE = "malware" @ContributesServiceApi(AppScope::class) interface MaliciousSiteService { + @AuthRequired @GET("$BASE_URL$HASH_PREFIX_PATH?$CATEGORY=$PHISHING") suspend fun getPhishingHashPrefixes(@Query("revision") revision: Int): HashPrefixResponse + @AuthRequired @GET("$BASE_URL$HASH_PREFIX_PATH?$CATEGORY=$MALWARE") suspend fun getMalwareHashPrefixes(@Query("revision") revision: Int): HashPrefixResponse + @AuthRequired @GET("$BASE_URL$FILTER_SET_PATH?$CATEGORY=$PHISHING") suspend fun getPhishingFilterSet(@Query("revision") revision: Int): FilterSetResponse + @AuthRequired @GET("$BASE_URL$FILTER_SET_PATH?$CATEGORY=$MALWARE") suspend fun getMalwareFilterSet(@Query("revision") revision: Int): FilterSetResponse + @AuthRequired @GET("$BASE_URL/matches") suspend fun getMatches(@Query("hashPrefix") hashPrefix: String): MatchesResponse + @AuthRequired @GET("$BASE_URL/revision") suspend fun getRevision(): RevisionResponse } @@ -83,3 +89,10 @@ data class MatchResponse( data class RevisionResponse( val revision: Int, ) + +/** + * This annotation is used in interceptors to be able to intercept the annotated service calls + */ +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.RUNTIME) +annotation class AuthRequired