Skip to content

Commit 99c4f6b

Browse files
committed
Implement 3P GetAppCheckToken API.
1 parent 91681dd commit 99c4f6b

File tree

2 files changed

+88
-8
lines changed

2 files changed

+88
-8
lines changed

appcheck/firebase-appcheck/src/main/java/com/google/firebase/appcheck/FirebaseAppCheck.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import android.annotation.SuppressLint;
1818
import androidx.annotation.NonNull;
19+
import com.google.android.gms.tasks.Task;
1920
import com.google.firebase.FirebaseApp;
2021
import com.google.firebase.appcheck.interop.AppCheckTokenListener;
2122
import com.google.firebase.appcheck.interop.InternalAppCheckTokenProvider;
@@ -69,4 +70,30 @@ public abstract void installAppCheckProviderFactory(
6970

7071
/** Sets the {@code isTokenAutoRefreshEnabled} flag. */
7172
public abstract void setTokenAutoRefreshEnabled(boolean isTokenAutoRefreshEnabled);
73+
74+
/**
75+
* Requests a Firebase App Check token. This method should be used ONLY if you need to authorize
76+
* requests to a non-Firebase backend. Requests to Firebase backends are authorized automatically
77+
* if configured.
78+
*/
79+
@NonNull
80+
public abstract Task<AppCheckToken> getAppCheckToken(boolean forceRefresh);
81+
82+
/**
83+
* Registers an {@link AppCheckListener} to changes in the token state. This method should be used
84+
* ONLY if you need to authorize requests to a non-Firebase backend. Requests to Firebase backends
85+
* are authorized automatically if configured.
86+
*/
87+
public abstract void addAppCheckListener(@NonNull AppCheckListener listener);
88+
89+
/** Unregisters an {@link AppCheckListener} to changes in the token state. */
90+
public abstract void removeAppCheckListener(@NonNull AppCheckListener listener);
91+
92+
public interface AppCheckListener {
93+
/**
94+
* This method gets invoked on the UI thread on changes to the token state. Does not trigger on
95+
* token expiry.
96+
*/
97+
void onAppCheckTokenChanged(@NonNull AppCheckToken token);
98+
}
7299
}

appcheck/firebase-appcheck/src/main/java/com/google/firebase/appcheck/internal/DefaultFirebaseAppCheck.java

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public class DefaultFirebaseAppCheck extends FirebaseAppCheck {
4646
private final Provider<UserAgentPublisher> userAgentPublisherProvider;
4747
private final Provider<HeartBeatInfo> heartBeatInfoProvider;
4848
private final List<AppCheckTokenListener> appCheckTokenListenerList;
49+
private final List<AppCheckListener> appCheckListenerList;
4950
private final StorageHelper storageHelper;
5051
private final TokenRefreshManager tokenRefreshManager;
5152
private final Clock clock;
@@ -65,6 +66,7 @@ public DefaultFirebaseAppCheck(
6566
this.userAgentPublisherProvider = userAgentPublisherProvider;
6667
this.heartBeatInfoProvider = heartBeatInfoProvider;
6768
this.appCheckTokenListenerList = new ArrayList<>();
69+
this.appCheckListenerList = new ArrayList<>();
6870
this.storageHelper =
6971
new StorageHelper(firebaseApp.getApplicationContext(), firebaseApp.getPersistenceKey());
7072
this.tokenRefreshManager =
@@ -110,7 +112,8 @@ public void resetAppCheckState() {
110112
public void addAppCheckTokenListener(@NonNull AppCheckTokenListener listener) {
111113
checkNotNull(listener);
112114
appCheckTokenListenerList.add(listener);
113-
tokenRefreshManager.onListenerCountChanged(appCheckTokenListenerList.size());
115+
tokenRefreshManager.onListenerCountChanged(
116+
appCheckTokenListenerList.size() + appCheckListenerList.size());
114117
// If there is a token available, trigger the listener with the current token.
115118
if (hasValidToken()) {
116119
listener.onAppCheckTokenChanged(
@@ -122,7 +125,28 @@ public void addAppCheckTokenListener(@NonNull AppCheckTokenListener listener) {
122125
public void removeAppCheckTokenListener(@NonNull AppCheckTokenListener listener) {
123126
checkNotNull(listener);
124127
appCheckTokenListenerList.remove(listener);
125-
tokenRefreshManager.onListenerCountChanged(appCheckTokenListenerList.size());
128+
tokenRefreshManager.onListenerCountChanged(
129+
appCheckTokenListenerList.size() + appCheckListenerList.size());
130+
}
131+
132+
@Override
133+
public void addAppCheckListener(@NonNull AppCheckListener listener) {
134+
checkNotNull(listener);
135+
appCheckListenerList.add(listener);
136+
tokenRefreshManager.onListenerCountChanged(
137+
appCheckTokenListenerList.size() + appCheckListenerList.size());
138+
// If there is a token available, trigger the listener with the current token.
139+
if (hasValidToken()) {
140+
listener.onAppCheckTokenChanged(cachedToken);
141+
}
142+
}
143+
144+
@Override
145+
public void removeAppCheckListener(@NonNull AppCheckListener listener) {
146+
checkNotNull(listener);
147+
appCheckListenerList.remove(listener);
148+
tokenRefreshManager.onListenerCountChanged(
149+
appCheckTokenListenerList.size() + appCheckListenerList.size());
126150
}
127151

128152
@NonNull
@@ -137,22 +161,31 @@ public Task<AppCheckTokenResult> getToken(boolean forceRefresh) {
137161
new FirebaseException("No AppCheckProvider installed.")));
138162
}
139163
// TODO: Cache the in-flight task.
164+
return fetchTokenResultFromProvider();
165+
}
166+
167+
@NonNull
168+
@Override
169+
public Task<AppCheckToken> getAppCheckToken(boolean forceRefresh) {
170+
if (!forceRefresh && hasValidToken()) {
171+
return Tasks.forResult(cachedToken);
172+
}
173+
if (appCheckProvider == null) {
174+
return Tasks.forException(new FirebaseException("No AppCheckProvider installed."));
175+
}
140176
return fetchTokenFromProvider();
141177
}
142178

143179
/** Fetches an {@link AppCheckTokenResult} via the installed {@link AppCheckProvider}. */
144-
Task<AppCheckTokenResult> fetchTokenFromProvider() {
145-
return appCheckProvider
146-
.getToken()
180+
Task<AppCheckTokenResult> fetchTokenResultFromProvider() {
181+
return fetchTokenFromProvider()
147182
.continueWithTask(
148183
new Continuation<AppCheckToken, Task<AppCheckTokenResult>>() {
149184
@Override
150185
public Task<AppCheckTokenResult> then(@NonNull Task<AppCheckToken> task) {
151186
if (task.isSuccessful()) {
152-
AppCheckToken token = task.getResult();
153-
updateStoredToken(token);
154187
AppCheckTokenResult tokenResult =
155-
DefaultAppCheckTokenResult.constructFromAppCheckToken(token);
188+
DefaultAppCheckTokenResult.constructFromAppCheckToken(task.getResult());
156189
for (AppCheckTokenListener listener : appCheckTokenListenerList) {
157190
listener.onAppCheckTokenChanged(tokenResult);
158191
}
@@ -168,6 +201,26 @@ public Task<AppCheckTokenResult> then(@NonNull Task<AppCheckToken> task) {
168201
});
169202
}
170203

204+
/** Fetches an {@link AppCheckToken} via the installed {@link AppCheckProvider}. */
205+
Task<AppCheckToken> fetchTokenFromProvider() {
206+
return appCheckProvider
207+
.getToken()
208+
.continueWithTask(
209+
new Continuation<AppCheckToken, Task<AppCheckToken>>() {
210+
@Override
211+
public Task<AppCheckToken> then(@NonNull Task<AppCheckToken> task) {
212+
if (task.isSuccessful()) {
213+
AppCheckToken token = task.getResult();
214+
updateStoredToken(token);
215+
for (AppCheckListener listener : appCheckListenerList) {
216+
listener.onAppCheckTokenChanged(token);
217+
}
218+
}
219+
return task;
220+
}
221+
});
222+
}
223+
171224
@Nullable
172225
String getUserAgent() {
173226
return userAgentPublisherProvider.get() != null

0 commit comments

Comments
 (0)