Skip to content

Commit

Permalink
Fix Part of #5084: Initialize Appcheck (#5115)
Browse files Browse the repository at this point in the history
## Explanation
Fixes Part of #5084. This is PR 6 of 6 Planned PRs.

This PR adds Firebase AppCheck and Play Integrity dependencies to the
project. It also initializes AppCheck.

Once a new production build is released with this commit, requests to
all our Firebase resources will include an attestation token, and we
will be able to begin monitoring the type of requests we receive. We
will use this data to inform when we will fully enforce AppCheck for all
Firebase access, after gaining an understanding of how many active users
would be impacted(unable to upload logs to Firestore).

To test this, I added a [debug
token](https://firebase.google.com/docs/app-check/android/debug-provider#emulator)
to the firebase console, to be used to verify our requests to Firestore.

<img width="1405" alt="Screenshot 2024-01-24 at 09 33 25"
src="https://github.com/oppia/oppia-android/assets/59600948/034f3176-b5cf-465a-858d-d55fd6495987">

<img width="918" alt="Screenshot 2024-01-24 at 09 45 54"
src="https://github.com/oppia/oppia-android/assets/59600948/19295576-8540-4890-b30b-0c6defb0a670">

#### The Appcheck console

<img width="1062" alt="Screenshot 2024-01-24 at 09 06 17"
src="https://github.com/oppia/oppia-android/assets/59600948/30c09bd1-f9bd-412d-8510-9fc8f9f5dd65">

<img width="1062" alt="Screenshot 2024-01-24 at 09 06 02"
src="https://github.com/oppia/oppia-android/assets/59600948/d4c3a8b0-fb4a-4531-89d3-c2783b9d702f">

<img width="1062" alt="Screenshot 2024-01-24 at 09 05 48"
src="https://github.com/oppia/oppia-android/assets/59600948/0423ea9d-db48-47c6-bbeb-7af905fc0785">

#### Test on the release token fetch
<img width="1377" alt="Screenshot 2024-01-24 at 08 57 10"
src="https://github.com/oppia/oppia-android/assets/59600948/0deee04b-ca34-482f-9663-b3959dbdda6d">


## Essential Checklist
<!-- Please tick the relevant boxes by putting an "x" in them. -->
- [x] The PR title and explanation each start with "Fix #bugnum: " (If
this PR fixes part of an issue, prefix the title with "Fix part of
#bugnum: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).

## For UI-specific PRs only
<!-- Delete these section if this PR does not include UI-related
changes. -->
If your PR includes UI-related changes, then:
- Add screenshots for portrait/landscape for both a tablet & phone of
the before & after UI changes
- For the screenshots above, include both English and pseudo-localized
(RTL) screenshots (see [RTL
guide](https://github.com/oppia/oppia-android/wiki/RTL-Guidelines))
- Add a video showing the full UX flow with a screen reader enabled (see
[accessibility
guide](https://github.com/oppia/oppia-android/wiki/Accessibility-A11y-Guide))
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing

---------

Co-authored-by: Ben Henning <ben@oppia.org>
  • Loading branch information
adhiamboperes and BenHenning authored Feb 13, 2024
1 parent 4a07d8d commit f7b9260
Show file tree
Hide file tree
Showing 10 changed files with 312 additions and 16 deletions.
3 changes: 3 additions & 0 deletions app/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -1022,6 +1022,9 @@ android_library(
name = "firestore_deps",
exports = [
"//third_party:com_google_auto_value_auto-value-annotations",
"//third_party:com_google_firebase_firebase-appcheck",
"//third_party:com_google_firebase_firebase-appcheck-debug",
"//third_party:com_google_firebase_firebase-appcheck-playintegrity",
"//third_party:org_checkerframework_checker-qual",
],
)
Expand Down
3 changes: 3 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ dependencies {
'com.google.dagger:dagger:2.24',
'com.google.firebase:firebase-analytics:17.5.0',
'com.google.firebase:firebase-analytics-ktx:17.5.0',
'com.google.firebase:firebase-appcheck:16.0.0',
'com.google.firebase:firebase-appcheck-debug:16.0.0',
'com.google.firebase:firebase-appcheck-playintegrity:16.0.0',
'com.google.firebase:firebase-core:17.5.0',
'com.google.firebase:firebase-crashlytics:17.0.0',
'com.google.firebase:firebase-firestore-ktx:24.2.1',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ import androidx.multidex.MultiDexApplication
import androidx.work.Configuration
import androidx.work.WorkManager
import com.google.firebase.FirebaseApp
import com.google.firebase.appcheck.FirebaseAppCheck
import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory
import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory
import org.oppia.android.app.activity.ActivityComponent
import org.oppia.android.app.activity.ActivityComponentFactory
import org.oppia.android.app.model.BuildFlavor
import org.oppia.android.domain.oppialogger.ApplicationStartupListener

/** The root base [Application] of the Oppia app. */
Expand Down Expand Up @@ -47,6 +51,20 @@ abstract class AbstractOppiaApplication(
// TODO(#4751): Re-enable WorkManager for S+.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
FirebaseApp.initializeApp(applicationContext)
// FirebaseAppCheck protects our API resources from abuse. It works with Firebase services,
// Google Cloud services, and can also be implemented for our own APIs.
// See https://firebase.google.com/docs/app-check for currently supported Firebase products.
// Note that as of this code being checked in, only the app's Firestore usage is affected by
// App Check (Analytics is NOT affected).
if (component.getCurrentBuildFlavor() == BuildFlavor.DEVELOPER) {
FirebaseAppCheck.getInstance().installAppCheckProviderFactory(
DebugAppCheckProviderFactory.getInstance(),
)
} else {
FirebaseAppCheck.getInstance().installAppCheckProviderFactory(
PlayIntegrityAppCheckProviderFactory.getInstance(),
)
}
WorkManager.initialize(applicationContext, workManagerConfiguration)
val workManager = WorkManager.getInstance(applicationContext)
component.getAnalyticsStartupListenerStartupListeners().forEach { it.onCreate(workManager) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.app.Application
import androidx.work.Configuration
import dagger.BindsInstance
import org.oppia.android.app.activity.ActivityComponentImpl
import org.oppia.android.app.model.BuildFlavor
import org.oppia.android.domain.oppialogger.ApplicationStartupListener
import org.oppia.android.domain.oppialogger.analytics.AnalyticsStartupListener
import javax.inject.Provider
Expand All @@ -30,4 +31,6 @@ interface ApplicationComponent : ApplicationInjector {
fun getAnalyticsStartupListenerStartupListeners(): Set<AnalyticsStartupListener>

fun getWorkManagerConfiguration(): Configuration

fun getCurrentBuildFlavor(): BuildFlavor
}
1 change: 1 addition & 0 deletions domain/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ TEST_DEPS = [
":interaction_object_test_builder",
"//app:crashlytics",
"//app:crashlytics_deps",
"//app:firestore_deps",
"//app/src/main/java/org/oppia/android/app/application/testing:testing_build_flavor_module",
"//config/src/java/org/oppia/android/config:all_languages_config",
"//data/src/main/java/org/oppia/android/data/backends/gae:network_config_prod_module",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class AuthenticationController @Inject constructor(
}
} catch (e: TimeoutCancellationException) {
deferredResult.complete(
AsyncResult.Failure(IllegalStateException(e))
AsyncResult.Failure(e)
)
}
}
Expand All @@ -44,6 +44,6 @@ class AuthenticationController @Inject constructor(

companion object {
/** The amount of time the authentication task should run before timing out. */
const val AUTHENTICATION_TIMEOUT_MILLIS = 30_000L
private const val AUTHENTICATION_TIMEOUT_MILLIS = 30_000L
}
}
33 changes: 33 additions & 0 deletions scripts/assets/maven_dependencies.textproto
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,39 @@ maven_dependency {
}
}
}
maven_dependency {
artifact_name: "com.google.firebase:firebase-appcheck-debug:16.0.0"
artifact_version: "16.0.0"
license {
license_name: "The Apache Software License, Version 2.0"
original_link: "https://www.apache.org/licenses/LICENSE-2.0.txt"
scrapable_link {
url: "https://www.apache.org/licenses/LICENSE-2.0.txt"
}
}
}
maven_dependency {
artifact_name: "com.google.firebase:firebase-appcheck-playintegrity:16.0.0"
artifact_version: "16.0.0"
license {
license_name: "The Apache Software License, Version 2.0"
original_link: "https://www.apache.org/licenses/LICENSE-2.0.txt"
scrapable_link {
url: "https://www.apache.org/licenses/LICENSE-2.0.txt"
}
}
}
maven_dependency {
artifact_name: "com.google.firebase:firebase-appcheck:16.0.0"
artifact_version: "16.0.0"
license {
license_name: "The Apache Software License, Version 2.0"
original_link: "https://www.apache.org/licenses/LICENSE-2.0.txt"
scrapable_link {
url: "https://www.apache.org/licenses/LICENSE-2.0.txt"
}
}
}
maven_dependency {
artifact_name: "com.google.firebase:firebase-auth-ktx:19.3.1"
artifact_version: "19.3.1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,17 @@ class FakeFirebaseAuthWrapperImplTest {
@Test
fun testFakeAuthWrapper_simulateSignInSuccess_returnsFakeAuthStateSuccess() {
fakeFirebaseAuthWrapperImpl.simulateSignInSuccess()

val authState = fakeFirebaseAuthWrapperImpl.getAuthState()
assertThat(authState).isInstanceOf(FakeAuthState.SUCCESS::class.java)

assertThat(authState).isEqualTo(FakeAuthState.SUCCESS)
}

@Test
fun testFakeAuthWrapper_simulateSignInFailure_returnsFakeAuthStateFailure() {
fakeFirebaseAuthWrapperImpl.simulateSignInFailure()
val authState = fakeFirebaseAuthWrapperImpl.getAuthState()
assertThat(authState).isInstanceOf(FakeAuthState.FAILURE::class.java)

assertThat(authState).isEqualTo(FakeAuthState.FAILURE)
}

private fun setUpTestApplicationComponent() {
Expand Down
Loading

0 comments on commit f7b9260

Please sign in to comment.