Skip to content

Commit 7254e91

Browse files
authored
Add support for Auth Emulator (#1854)
1 parent 5342e3d commit 7254e91

29 files changed

+396
-203
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ google-services.json
1010

1111
crashlytics-build.properties
1212
auth/src/main/res/values/com_crashlytics_export_strings.xml
13+
*.log

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
- Update all dependencies to latest major version.
1+
- [All] Update all dependencies to latest major version.
22
- [Auth] Remove SupportVectorDrawablesButton (#1860) (contributed by @AryanNajafi)
3+
- [Auth] Add `AuthUI#useEmulator()` method to use FirebaseUI with the Firebase Auth Emulator (#1849)

app/src/main/AndroidManifest.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
android:roundIcon="@mipmap/ic_launcher_round"
1717
android:supportsRtl="true"
1818
android:theme="@style/AppTheme"
19-
tools:ignore="GoogleAppIndexingWarning">
19+
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute"
20+
android:usesCleartextTraffic="true">
2021

2122
<activity android:name=".ChooserActivity">
2223
<intent-filter>

app/src/main/java/com/firebase/uidemo/auth/AuthUiActivity.java

+24-2
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ public class AuthUiActivity extends AppCompatActivity {
109109
@BindView(R.id.hint_selector_enabled) CheckBox mEnableHintSelector;
110110
@BindView(R.id.allow_new_email_accounts) CheckBox mAllowNewEmailAccounts;
111111
@BindView(R.id.require_name) CheckBox mRequireName;
112+
@BindView(R.id.use_auth_emulator) CheckBox mUseEmulator;
112113

113114
@NonNull
114115
public static Intent createIntent(@NonNull Context context) {
@@ -189,6 +190,17 @@ public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
189190
}
190191
});
191192

193+
// useEmulator can't be reversed until the FirebaseApp is cleared, so we make this
194+
// checkbox "sticky" until the app is restarted
195+
mUseEmulator.setOnCheckedChangeListener(new OnCheckedChangeListener() {
196+
@Override
197+
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
198+
if (isChecked) {
199+
mUseEmulator.setEnabled(false);
200+
}
201+
}
202+
});
203+
192204
if (ConfigurationUtils.isGoogleMisconfigured(this)
193205
|| ConfigurationUtils.isFacebookMisconfigured(this)) {
194206
showSnackbar(R.string.configuration_required);
@@ -232,9 +244,19 @@ public void signInWithEmailLink(@Nullable String link) {
232244
startActivityForResult(buildSignInIntent(link), RC_SIGN_IN);
233245
}
234246

247+
@NonNull
248+
public AuthUI getAuthUI() {
249+
AuthUI authUI = AuthUI.getInstance();
250+
if (mUseEmulator.isChecked()) {
251+
authUI.useEmulator("10.0.2.2", 9099);
252+
}
253+
254+
return authUI;
255+
}
256+
235257
@NonNull
236258
public Intent buildSignInIntent(@Nullable String link) {
237-
AuthUI.SignInIntentBuilder builder = AuthUI.getInstance().createSignInIntentBuilder()
259+
AuthUI.SignInIntentBuilder builder = getAuthUI().createSignInIntentBuilder()
238260
.setTheme(getSelectedTheme())
239261
.setLogo(getSelectedLogo())
240262
.setAvailableProviders(getSelectedProviders())
@@ -274,7 +296,7 @@ public Intent buildSignInIntent(@Nullable String link) {
274296

275297
@OnClick(R.id.sign_in_silent)
276298
public void silentSignIn() {
277-
AuthUI.getInstance().silentSignIn(this, getSelectedProviders())
299+
getAuthUI().silentSignIn(this, getSelectedProviders())
278300
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
279301
@Override
280302
public void onComplete(@NonNull Task<AuthResult> task) {

app/src/main/res/layout/auth_ui_layout.xml

+7
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,13 @@
347347
android:checked="true"
348348
android:text="@string/options_require_name" />
349349

350+
<CheckBox
351+
android:id="@+id/use_auth_emulator"
352+
android:layout_width="wrap_content"
353+
android:layout_height="wrap_content"
354+
android:checked="false"
355+
android:text="@string/options_use_auth_emulator" />
356+
350357
</LinearLayout>
351358

352359
</ScrollView>

app/src/main/res/values/strings.xml

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
<string name="options_enable_hint_selector">Enable Smart Lock\'s hint selector</string>
6969
<string name="options_allow_new_email_acccount">Allow new account creation</string>
7070
<string name="options_require_name">Require first/last name with email accounts.</string>
71+
<string name="options_use_auth_emulator">Connect to auth emulator (localhost:9099).</string>
7172

7273
<string name="configuration_required">Configuration required - see README.md</string>
7374
<string name="google_label_missing_config">Google configuration missing</string>

auth/src/main/java/com/firebase/ui/auth/AuthUI.java

+56-4
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ public final class AuthUI {
109109
public static final String YAHOO_PROVIDER = "yahoo.com";
110110
public static final String APPLE_PROVIDER = "apple.com";
111111

112-
113112
/**
114113
* Default value for logo resource, omits the logo from the {@link AuthMethodPickerActivity}.
115114
*/
@@ -161,6 +160,9 @@ public final class AuthUI {
161160
private final FirebaseApp mApp;
162161
private final FirebaseAuth mAuth;
163162

163+
private String mEmulatorHost = null;
164+
private int mEmulatorPort = -1;
165+
164166
private AuthUI(FirebaseApp app) {
165167
mApp = app;
166168
mAuth = FirebaseAuth.getInstance(mApp);
@@ -196,6 +198,16 @@ public static AuthUI getInstance() {
196198
return getInstance(FirebaseApp.getInstance());
197199
}
198200

201+
/**
202+
* Retrieves the {@link AuthUI} instance associated the the specified app name.
203+
*
204+
* @throws IllegalStateException if the app is not initialized.
205+
*/
206+
@NonNull
207+
public static AuthUI getInstance(@NonNull String appName) {
208+
return getInstance(FirebaseApp.getInstance(appName));
209+
}
210+
199211
/**
200212
* Retrieves the {@link AuthUI} instance associated the the specified app.
201213
*/
@@ -223,6 +235,18 @@ public static AuthUI getInstance(@NonNull FirebaseApp app) {
223235
return authUi;
224236
}
225237

238+
@NonNull
239+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
240+
public FirebaseApp getApp() {
241+
return mApp;
242+
}
243+
244+
@NonNull
245+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
246+
public FirebaseAuth getAuth() {
247+
return mAuth;
248+
}
249+
226250
/**
227251
* Returns true if AuthUI can handle the intent.
228252
* <p>
@@ -460,6 +484,34 @@ public Task<Void> then(@NonNull Task<Void> task) {
460484
});
461485
}
462486

487+
/**
488+
* Connect to the Firebase Authentication emulator.
489+
* @see FirebaseAuth#useEmulator(String, int)
490+
*/
491+
public void useEmulator(@NonNull String host, int port) {
492+
Preconditions.checkArgument(port >= 0, "Port must be >= 0");
493+
Preconditions.checkArgument(port <= 65535, "Port must be <= 65535");
494+
mEmulatorHost = host;
495+
mEmulatorPort = port;
496+
497+
mAuth.useEmulator(host, port);
498+
}
499+
500+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
501+
public boolean isUseEmulator() {
502+
return mEmulatorHost != null && mEmulatorPort >= 0;
503+
}
504+
505+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
506+
public String getEmulatorHost() {
507+
return mEmulatorHost;
508+
}
509+
510+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
511+
public int getEmulatorPort() {
512+
return mEmulatorPort;
513+
}
514+
463515
private Task<Void> signOutIdps(@NonNull Context context) {
464516
if (ProviderAvailability.IS_FACEBOOK_AVAILABLE) {
465517
LoginManager.getInstance().logOut();
@@ -1160,9 +1212,9 @@ public YahooBuilder() {
11601212
*/
11611213
public static class GenericOAuthProviderBuilder extends Builder {
11621214

1163-
GenericOAuthProviderBuilder(@NonNull String providerId,
1164-
@NonNull String providerName,
1165-
int buttonId) {
1215+
public GenericOAuthProviderBuilder(@NonNull String providerId,
1216+
@NonNull String providerName,
1217+
int buttonId) {
11661218
super(providerId);
11671219

11681220
Preconditions.checkNotNull(providerId, "The provider ID cannot be null.");

auth/src/main/java/com/firebase/ui/auth/IdpResponse.java

+2
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ public IdpResponse build() {
381381
}
382382

383383
String providerId = mUser.getProviderId();
384+
384385
if (AuthUI.SOCIAL_PROVIDERS.contains(providerId) && TextUtils.isEmpty(mToken)) {
385386
throw new IllegalStateException(
386387
"Token cannot be null when using a non-email provider.");
@@ -390,6 +391,7 @@ public IdpResponse build() {
390391
throw new IllegalStateException(
391392
"Secret cannot be null when using the Twitter provider.");
392393
}
394+
393395
return new IdpResponse(mUser, mToken, mSecret, mPendingCredential, mIsNewUser);
394396
}
395397
}

auth/src/main/java/com/firebase/ui/auth/data/remote/AnonymousSignInHandler.java

+6-12
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@
2323

2424

2525
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
26-
public class AnonymousSignInHandler extends ProviderSignInBase<FlowParameters> {
26+
public class AnonymousSignInHandler extends SingleProviderSignInHandler<FlowParameters> {
2727

2828
@VisibleForTesting
2929
public FirebaseAuth mAuth;
3030

3131
public AnonymousSignInHandler(Application application) {
32-
super(application);
32+
super(application, AuthUI.ANONYMOUS_PROVIDER);
3333
}
3434

3535
@Override
@@ -38,7 +38,9 @@ protected void onCreate() {
3838
}
3939

4040
@Override
41-
public void startSignIn(@NonNull HelperActivityBase activity) {
41+
public void startSignIn(@NonNull FirebaseAuth auth,
42+
@NonNull HelperActivityBase activity,
43+
@NonNull String providerId) {
4244
setResult(Resource.<IdpResponse>forLoading());
4345

4446
// Calling signInAnonymously() will always return the same anonymous user if already
@@ -74,14 +76,6 @@ private IdpResponse initResponse(boolean isNewUser) {
7476
// TODO: We need to centralize the auth logic. ProviderSignInBase classes were originally
7577
// meant to only retrieve remote provider data.
7678
private FirebaseAuth getAuth() {
77-
FirebaseApp app = FirebaseApp.getInstance(getArguments().appName);
78-
return FirebaseAuth.getInstance(app);
79-
}
80-
81-
@Override
82-
public void startSignIn(@NonNull FirebaseAuth auth,
83-
@NonNull HelperActivityBase activity,
84-
@NonNull String providerId) {
85-
startSignIn(activity);
79+
return AuthUI.getInstance(getArguments().appName).getAuth();
8680
}
8781
}

auth/src/main/java/com/firebase/ui/auth/data/remote/EmailSignInHandler.java

+8-10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import android.app.Application;
44
import android.content.Intent;
55

6+
import com.firebase.ui.auth.AuthUI;
67
import com.firebase.ui.auth.ErrorCodes;
78
import com.firebase.ui.auth.IdpResponse;
89
import com.firebase.ui.auth.data.model.Resource;
@@ -11,20 +12,24 @@
1112
import com.firebase.ui.auth.ui.email.EmailActivity;
1213
import com.firebase.ui.auth.viewmodel.ProviderSignInBase;
1314
import com.firebase.ui.auth.viewmodel.RequestCodes;
15+
import com.google.firebase.auth.EmailAuthCredential;
16+
import com.google.firebase.auth.EmailAuthProvider;
1417
import com.google.firebase.auth.FirebaseAuth;
1518

1619
import androidx.annotation.NonNull;
1720
import androidx.annotation.Nullable;
1821
import androidx.annotation.RestrictTo;
1922

2023
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
21-
public class EmailSignInHandler extends ProviderSignInBase<Void> {
24+
public class EmailSignInHandler extends SingleProviderSignInHandler<Void> {
2225
public EmailSignInHandler(Application application) {
23-
super(application);
26+
super(application, EmailAuthProvider.PROVIDER_ID);
2427
}
2528

2629
@Override
27-
public void startSignIn(@NonNull HelperActivityBase activity) {
30+
public void startSignIn(@NonNull FirebaseAuth auth,
31+
@NonNull HelperActivityBase activity,
32+
@NonNull String providerId) {
2833
activity.startActivityForResult(
2934
EmailActivity.createIntent(activity, activity.getFlowParams()),
3035
RequestCodes.EMAIL_FLOW);
@@ -43,11 +48,4 @@ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent d
4348
}
4449
}
4550
}
46-
47-
@Override
48-
public void startSignIn(@NonNull FirebaseAuth auth,
49-
@NonNull HelperActivityBase activity,
50-
@NonNull String providerId) {
51-
startSignIn(activity);
52-
}
5351
}

auth/src/main/java/com/firebase/ui/auth/data/remote/FacebookSignInHandler.java

+5-10
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
import androidx.annotation.RestrictTo;
4040

4141
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
42-
public class FacebookSignInHandler extends ProviderSignInBase<AuthUI.IdpConfig> {
42+
public class FacebookSignInHandler extends SingleProviderSignInHandler<AuthUI.IdpConfig> {
4343
private static final String EMAIL = "email";
4444
private static final String PUBLIC_PROFILE = "public_profile";
4545

@@ -49,7 +49,7 @@ public class FacebookSignInHandler extends ProviderSignInBase<AuthUI.IdpConfig>
4949
private final CallbackManager mCallbackManager = CallbackManager.Factory.create();
5050

5151
public FacebookSignInHandler(Application application) {
52-
super(application);
52+
super(application, FacebookAuthProvider.PROVIDER_ID);
5353
}
5454

5555
private static IdpResponse createIdpResponse(
@@ -80,7 +80,9 @@ protected void onCreate() {
8080
}
8181

8282
@Override
83-
public void startSignIn(@NonNull HelperActivityBase activity) {
83+
public void startSignIn(@NonNull FirebaseAuth auth,
84+
@NonNull HelperActivityBase activity,
85+
@NonNull String providerId) {
8486
WebDialog.setWebDialogTheme(activity.getFlowParams().themeId);
8587
LoginManager.getInstance().logInWithReadPermissions(activity, mPermissions);
8688
}
@@ -162,11 +164,4 @@ public void onCompleted(JSONObject object, GraphResponse response) {
162164
setResult(Resource.forSuccess(createIdpResponse(mResult, email, name, photoUri)));
163165
}
164166
}
165-
166-
@Override
167-
public void startSignIn(@NonNull FirebaseAuth auth,
168-
@NonNull HelperActivityBase activity,
169-
@NonNull String providerId) {
170-
startSignIn(activity);
171-
}
172167
}

0 commit comments

Comments
 (0)