Skip to content

Commit fbc0307

Browse files
committed
AppCheck integration with Firestore.
1 parent 424da4d commit fbc0307

File tree

19 files changed

+363
-54
lines changed

19 files changed

+363
-54
lines changed

firebase-firestore/firebase-firestore.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ dependencies {
141141
implementation project(':protolite-well-known-types')
142142
implementation project(':firebase-database-collection')
143143
implementation project(':firebase-components')
144+
implementation project(':appcheck:firebase-appcheck-interop')
144145

145146

146147
//To provide @Generated annotations

firebase-firestore/src/androidTest/java/com/google/firebase/firestore/AccessHelper.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.google.android.gms.tasks.Task;
1919
import com.google.firebase.FirebaseApp;
2020
import com.google.firebase.firestore.auth.CredentialsProvider;
21+
import com.google.firebase.firestore.auth.User;
2122
import com.google.firebase.firestore.model.DatabaseId;
2223
import com.google.firebase.firestore.util.AsyncQueue;
2324

@@ -29,15 +30,17 @@ public static FirebaseFirestore newFirebaseFirestore(
2930
Context context,
3031
DatabaseId databaseId,
3132
String persistenceKey,
32-
CredentialsProvider credentialsProvider,
33+
CredentialsProvider<User> authProvider,
34+
CredentialsProvider<String> appCheckProvider,
3335
AsyncQueue asyncQueue,
3436
FirebaseApp firebaseApp,
3537
FirebaseFirestore.InstanceRegistry instanceRegistry) {
3638
return new FirebaseFirestore(
3739
context,
3840
databaseId,
3941
persistenceKey,
40-
credentialsProvider,
42+
authProvider,
43+
appCheckProvider,
4144
asyncQueue,
4245
firebaseApp,
4346
instanceRegistry,

firebase-firestore/src/androidTest/java/com/google/firebase/firestore/remote/RemoteStoreTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public void testRemoteStoreStreamStopsWhenNetworkUnreachable() {
4545
IntegrationTestUtil.testEnvDatabaseInfo(),
4646
testQueue,
4747
null,
48+
null,
4849
ApplicationProvider.getApplicationContext(),
4950
null);
5051
Semaphore networkChangeSemaphore = new Semaphore(0);

firebase-firestore/src/androidTest/java/com/google/firebase/firestore/remote/StreamTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.google.firebase.firestore.model.SnapshotVersion;
3333
import com.google.firebase.firestore.model.mutation.Mutation;
3434
import com.google.firebase.firestore.model.mutation.MutationResult;
35+
import com.google.firebase.firestore.testutil.EmptyAppCheckTokenProvider;
3536
import com.google.firebase.firestore.testutil.EmptyCredentialsProvider;
3637
import com.google.firebase.firestore.testutil.IntegrationTestUtil;
3738
import com.google.firebase.firestore.util.AsyncQueue;
@@ -113,6 +114,7 @@ private WriteStream createAndOpenWriteStream(
113114
IntegrationTestUtil.testEnvDatabaseInfo(),
114115
testQueue,
115116
new EmptyCredentialsProvider(),
117+
new EmptyAppCheckTokenProvider(),
116118
ApplicationProvider.getApplicationContext(),
117119
null);
118120
final WriteStream writeStream = datastore.createWriteStream(callback);
@@ -138,6 +140,7 @@ public void testWatchStreamStopBeforeHandshake() throws Exception {
138140
IntegrationTestUtil.testEnvDatabaseInfo(),
139141
testQueue,
140142
new EmptyCredentialsProvider(),
143+
new EmptyAppCheckTokenProvider(),
141144
ApplicationProvider.getApplicationContext(),
142145
mockGrpcProvider);
143146
StreamStatusCallback streamCallback = new StreamStatusCallback() {};
@@ -160,6 +163,7 @@ public void testWriteStreamStopAfterHandshake() throws Exception {
160163
IntegrationTestUtil.testEnvDatabaseInfo(),
161164
testQueue,
162165
new EmptyCredentialsProvider(),
166+
new EmptyAppCheckTokenProvider(),
163167
ApplicationProvider.getApplicationContext(),
164168
null);
165169
final WriteStream[] writeStreamWrapper = new WriteStream[1];
@@ -207,6 +211,7 @@ public void testWriteStreamStopPartial() throws Exception {
207211
IntegrationTestUtil.testEnvDatabaseInfo(),
208212
testQueue,
209213
new EmptyCredentialsProvider(),
214+
new EmptyAppCheckTokenProvider(),
210215
ApplicationProvider.getApplicationContext(),
211216
null);
212217
StreamStatusCallback streamCallback = new StreamStatusCallback() {};
@@ -287,6 +292,7 @@ public void testStreamRefreshesTokenUponExpiration() throws Exception {
287292
IntegrationTestUtil.testEnvDatabaseInfo(),
288293
testQueue,
289294
mockCredentialsProvider,
295+
new EmptyAppCheckTokenProvider(),
290296
ApplicationProvider.getApplicationContext(),
291297
null);
292298
StreamStatusCallback callback = new StreamStatusCallback();
@@ -316,6 +322,7 @@ public void testTokenIsNotInvalidatedOnceStreamIsHealthy() throws Exception {
316322
IntegrationTestUtil.testEnvDatabaseInfo(),
317323
testQueue,
318324
mockCredentialsProvider,
325+
new EmptyAppCheckTokenProvider(),
319326
ApplicationProvider.getApplicationContext(),
320327
null);
321328
StreamStatusCallback callback = new StreamStatusCallback();

firebase-firestore/src/androidTest/java/com/google/firebase/firestore/testutil/IntegrationTestUtil.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ public static FirebaseFirestore testFirestore(
272272
databaseId,
273273
persistenceKey,
274274
MockCredentialsProvider.instance(),
275+
new EmptyAppCheckTokenProvider(),
275276
asyncQueue,
276277
/*firebaseApp=*/ null,
277278
/*instanceRegistry=*/ (dbId) -> {});

firebase-firestore/src/main/java/com/google/firebase/firestore/FirebaseFirestore.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,14 @@
2727
import com.google.android.gms.tasks.TaskCompletionSource;
2828
import com.google.android.gms.tasks.Tasks;
2929
import com.google.firebase.FirebaseApp;
30+
import com.google.firebase.appcheck.interop.InternalAppCheckTokenProvider;
3031
import com.google.firebase.auth.internal.InternalAuthProvider;
3132
import com.google.firebase.emulators.EmulatedServiceSettings;
3233
import com.google.firebase.firestore.FirebaseFirestoreException.Code;
3334
import com.google.firebase.firestore.auth.CredentialsProvider;
35+
import com.google.firebase.firestore.auth.FirebaseAppCheckTokenProvider;
3436
import com.google.firebase.firestore.auth.FirebaseAuthCredentialsProvider;
37+
import com.google.firebase.firestore.auth.User;
3538
import com.google.firebase.firestore.core.ActivityScope;
3639
import com.google.firebase.firestore.core.AsyncEventListener;
3740
import com.google.firebase.firestore.core.DatabaseInfo;
@@ -50,6 +53,7 @@
5053
import com.google.firebase.firestore.util.Logger;
5154
import com.google.firebase.firestore.util.Logger.Level;
5255
import com.google.firebase.inject.Deferred;
56+
import com.google.firebase.inject.Provider;
5357
import java.io.ByteArrayInputStream;
5458
import java.io.InputStream;
5559
import java.nio.ByteBuffer;
@@ -85,7 +89,8 @@ public interface InstanceRegistry {
8589
// databaseId itself that needs locking; it just saves us creating a separate lock object.
8690
private final DatabaseId databaseId;
8791
private final String persistenceKey;
88-
private final CredentialsProvider credentialsProvider;
92+
private final CredentialsProvider<User> authProvider;
93+
private final CredentialsProvider<String> appCheckProvider;
8994
private final AsyncQueue asyncQueue;
9095
private final FirebaseApp firebaseApp;
9196
private final UserDataReader userDataReader;
@@ -124,7 +129,8 @@ private static FirebaseFirestore getInstance(@NonNull FirebaseApp app, @NonNull
124129
static FirebaseFirestore newInstance(
125130
@NonNull Context context,
126131
@NonNull FirebaseApp app,
127-
@NonNull Deferred<InternalAuthProvider> authProvider,
132+
@NonNull Deferred<InternalAuthProvider> deferredAuthProvider,
133+
@NonNull Provider<InternalAppCheckTokenProvider> appCheckTokenProvider,
128134
@NonNull String database,
129135
@NonNull InstanceRegistry instanceRegistry,
130136
@Nullable GrpcMetadataProvider metadataProvider) {
@@ -136,7 +142,10 @@ static FirebaseFirestore newInstance(
136142

137143
AsyncQueue queue = new AsyncQueue();
138144

139-
CredentialsProvider provider = new FirebaseAuthCredentialsProvider(authProvider);
145+
CredentialsProvider<User> authProvider =
146+
new FirebaseAuthCredentialsProvider(deferredAuthProvider);
147+
CredentialsProvider<String> appCheckProvider =
148+
new FirebaseAppCheckTokenProvider(appCheckTokenProvider);
140149

141150
// Firestore uses a different database for each app name. Note that we don't use
142151
// app.getPersistenceKey() here because it includes the application ID which is related
@@ -149,7 +158,8 @@ static FirebaseFirestore newInstance(
149158
context,
150159
databaseId,
151160
persistenceKey,
152-
provider,
161+
authProvider,
162+
appCheckProvider,
153163
queue,
154164
app,
155165
instanceRegistry,
@@ -162,7 +172,8 @@ static FirebaseFirestore newInstance(
162172
Context context,
163173
DatabaseId databaseId,
164174
String persistenceKey,
165-
CredentialsProvider credentialsProvider,
175+
CredentialsProvider<User> authProvider,
176+
CredentialsProvider<String> appCheckProvider,
166177
AsyncQueue asyncQueue,
167178
@Nullable FirebaseApp firebaseApp,
168179
InstanceRegistry instanceRegistry,
@@ -171,7 +182,8 @@ static FirebaseFirestore newInstance(
171182
this.databaseId = checkNotNull(checkNotNull(databaseId));
172183
this.userDataReader = new UserDataReader(databaseId);
173184
this.persistenceKey = checkNotNull(persistenceKey);
174-
this.credentialsProvider = checkNotNull(credentialsProvider);
185+
this.authProvider = checkNotNull(authProvider);
186+
this.appCheckProvider = checkNotNull(appCheckProvider);
175187
this.asyncQueue = checkNotNull(asyncQueue);
176188
// NOTE: We allow firebaseApp to be null in tests only.
177189
this.firebaseApp = firebaseApp;
@@ -242,7 +254,13 @@ private void ensureClientConfigured() {
242254

243255
client =
244256
new FirestoreClient(
245-
context, databaseInfo, settings, credentialsProvider, asyncQueue, metadataProvider);
257+
context,
258+
databaseInfo,
259+
settings,
260+
authProvider,
261+
appCheckProvider,
262+
asyncQueue,
263+
metadataProvider);
246264
}
247265
}
248266

firebase-firestore/src/main/java/com/google/firebase/firestore/FirestoreMultiDbComponent.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@
2222
import com.google.firebase.FirebaseApp;
2323
import com.google.firebase.FirebaseAppLifecycleListener;
2424
import com.google.firebase.FirebaseOptions;
25+
import com.google.firebase.appcheck.interop.InternalAppCheckTokenProvider;
2526
import com.google.firebase.auth.internal.InternalAuthProvider;
2627
import com.google.firebase.firestore.remote.GrpcMetadataProvider;
2728
import com.google.firebase.inject.Deferred;
29+
import com.google.firebase.inject.Provider;
2830
import java.util.ArrayList;
2931
import java.util.HashMap;
3032
import java.util.Map;
@@ -42,16 +44,19 @@ class FirestoreMultiDbComponent
4244
private final FirebaseApp app;
4345
private final Context context;
4446
private final Deferred<InternalAuthProvider> authProvider;
47+
private final Provider<InternalAppCheckTokenProvider> appCheckProvider;
4548
private final GrpcMetadataProvider metadataProvider;
4649

4750
FirestoreMultiDbComponent(
4851
@NonNull Context context,
4952
@NonNull FirebaseApp app,
5053
@NonNull Deferred<InternalAuthProvider> authProvider,
54+
@NonNull Provider<InternalAppCheckTokenProvider> appCheckProvider,
5155
@Nullable GrpcMetadataProvider metadataProvider) {
5256
this.context = context;
5357
this.app = app;
5458
this.authProvider = authProvider;
59+
this.appCheckProvider = appCheckProvider;
5560
this.metadataProvider = metadataProvider;
5661
this.app.addLifecycleEventListener(this);
5762
}
@@ -63,7 +68,7 @@ synchronized FirebaseFirestore get(@NonNull String databaseId) {
6368
if (firestore == null) {
6469
firestore =
6570
FirebaseFirestore.newInstance(
66-
context, app, authProvider, databaseId, this, metadataProvider);
71+
context, app, authProvider, appCheckProvider, databaseId, this, metadataProvider);
6772
instances.put(databaseId, firestore);
6873
}
6974
return firestore;

firebase-firestore/src/main/java/com/google/firebase/firestore/FirestoreRegistrar.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import androidx.annotation.RestrictTo;
2020
import com.google.firebase.FirebaseApp;
2121
import com.google.firebase.FirebaseOptions;
22+
import com.google.firebase.appcheck.interop.InternalAppCheckTokenProvider;
2223
import com.google.firebase.auth.internal.InternalAuthProvider;
2324
import com.google.firebase.components.Component;
2425
import com.google.firebase.components.ComponentRegistrar;
@@ -48,13 +49,15 @@ public List<Component<?>> getComponents() {
4849
.add(Dependency.optionalProvider(HeartBeatInfo.class))
4950
.add(Dependency.optionalProvider(UserAgentPublisher.class))
5051
.add(Dependency.deferred(InternalAuthProvider.class))
52+
.add(Dependency.optionalProvider(InternalAppCheckTokenProvider.class))
5153
.add(Dependency.optional(FirebaseOptions.class))
5254
.factory(
5355
c ->
5456
new FirestoreMultiDbComponent(
5557
c.get(Context.class),
5658
c.get(FirebaseApp.class),
5759
c.getDeferred(InternalAuthProvider.class),
60+
c.getProvider(InternalAppCheckTokenProvider.class),
5861
new FirebaseClientGrpcMetadataProvider(
5962
c.getProvider(UserAgentPublisher.class),
6063
c.getProvider(HeartBeatInfo.class),

firebase-firestore/src/main/java/com/google/firebase/firestore/auth/CredentialsProvider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import com.google.firebase.firestore.util.Listener;
1919

2020
/** A CredentialsProvider has a method to fetch an authorization token. */
21-
public abstract class CredentialsProvider {
21+
public abstract class CredentialsProvider<T> {
2222
/**
2323
* Requests token for the current user. Use {@link #invalidateToken} to force-refresh the token.
2424
*
@@ -36,7 +36,7 @@ public abstract class CredentialsProvider {
3636
* Sets the listener to be notified of credential changes (sign-in / sign-out, token changes). It
3737
* is immediately called once with the initial user.
3838
*/
39-
public abstract void setChangeListener(Listener<User> changeListener);
39+
public abstract void setChangeListener(Listener<T> changeListener);
4040

4141
/** Removes the listener set with {@link #setChangeListener}. */
4242
public abstract void removeChangeListener();

0 commit comments

Comments
 (0)