|
41 | 41 | import com.firebase.ui.auth.util.data.PhoneNumberUtils;
|
42 | 42 | import com.firebase.ui.auth.util.data.ProviderUtils;
|
43 | 43 | import com.google.android.gms.auth.api.credentials.Credential;
|
| 44 | +import com.google.android.gms.auth.api.credentials.CredentialRequest; |
| 45 | +import com.google.android.gms.auth.api.credentials.CredentialRequestResponse; |
44 | 46 | import com.google.android.gms.auth.api.credentials.CredentialsClient;
|
45 | 47 | import com.google.android.gms.auth.api.signin.GoogleSignIn;
|
| 48 | +import com.google.android.gms.auth.api.signin.GoogleSignInAccount; |
46 | 49 | import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
|
47 | 50 | import com.google.android.gms.common.api.ApiException;
|
48 | 51 | import com.google.android.gms.common.api.CommonStatusCodes;
|
|
51 | 54 | import com.google.android.gms.tasks.Task;
|
52 | 55 | import com.google.android.gms.tasks.Tasks;
|
53 | 56 | import com.google.firebase.FirebaseApp;
|
| 57 | +import com.google.firebase.auth.AuthCredential; |
| 58 | +import com.google.firebase.auth.AuthResult; |
54 | 59 | import com.google.firebase.auth.EmailAuthProvider;
|
55 | 60 | import com.google.firebase.auth.FacebookAuthProvider;
|
56 | 61 | import com.google.firebase.auth.FirebaseAuth;
|
@@ -267,6 +272,85 @@ public static int getDefaultTheme() {
|
267 | 272 | return R.style.FirebaseUI;
|
268 | 273 | }
|
269 | 274 |
|
| 275 | + /** |
| 276 | + * Signs the user in without any UI if possible. If this operation fails, you can safely start a |
| 277 | + * UI-based sign-in flow knowing it is required. |
| 278 | + * |
| 279 | + * @param context requesting the user be signed in |
| 280 | + * @param desiredConfigs to use for silent sign in. Only Google and email are currently |
| 281 | + * supported, the rest will be ignored. |
| 282 | + * @return a task which indicates whether or not the user was successfully signed in. |
| 283 | + */ |
| 284 | + @NonNull |
| 285 | + public Task<AuthResult> silentSignIn(@NonNull Context context, |
| 286 | + @NonNull List<IdpConfig> configs) { |
| 287 | + if (mAuth.getCurrentUser() != null) { |
| 288 | + throw new IllegalArgumentException("User already signed in!"); |
| 289 | + } |
| 290 | + |
| 291 | + final Context appContext = context.getApplicationContext(); |
| 292 | + final IdpConfig google = |
| 293 | + ProviderUtils.getConfigFromIdps(configs, GoogleAuthProvider.PROVIDER_ID); |
| 294 | + final IdpConfig email = |
| 295 | + ProviderUtils.getConfigFromIdps(configs, EmailAuthProvider.PROVIDER_ID); |
| 296 | + |
| 297 | + if (google == null && email == null) { |
| 298 | + throw new IllegalArgumentException("No supported providers were supplied. " + |
| 299 | + "Add either Google or email support."); |
| 300 | + } |
| 301 | + |
| 302 | + final GoogleSignInOptions googleOptions; |
| 303 | + if (google == null) { |
| 304 | + googleOptions = null; |
| 305 | + } else { |
| 306 | + GoogleSignInAccount last = GoogleSignIn.getLastSignedInAccount(appContext); |
| 307 | + if (last != null && last.getIdToken() != null) { |
| 308 | + return mAuth.signInWithCredential(GoogleAuthProvider.getCredential( |
| 309 | + last.getIdToken(), null)); |
| 310 | + } |
| 311 | + |
| 312 | + googleOptions = google.getParams() |
| 313 | + .getParcelable(ExtraConstants.GOOGLE_SIGN_IN_OPTIONS); |
| 314 | + } |
| 315 | + |
| 316 | + return GoogleApiUtils.getCredentialsClient(context) |
| 317 | + .request(new CredentialRequest.Builder() |
| 318 | + // We can support both email and Google at the same time here because they |
| 319 | + // are mutually exclusive. If a user signs in with Google, their email |
| 320 | + // account will automatically be upgraded (a.k.a. replaced) with the Google |
| 321 | + // one, meaning Smart Lock won't have to show the picker UI. |
| 322 | + .setPasswordLoginSupported(email != null) |
| 323 | + .setAccountTypes(google == null ? null : |
| 324 | + ProviderUtils.providerIdToAccountType(GoogleAuthProvider.PROVIDER_ID)) |
| 325 | + .build()) |
| 326 | + .continueWithTask(new Continuation<CredentialRequestResponse, Task<AuthResult>>() { |
| 327 | + @Override |
| 328 | + public Task<AuthResult> then(@NonNull Task<CredentialRequestResponse> task) { |
| 329 | + Credential credential = task.getResult().getCredential(); |
| 330 | + String email = credential.getId(); |
| 331 | + String password = credential.getPassword(); |
| 332 | + |
| 333 | + if (TextUtils.isEmpty(password)) { |
| 334 | + return GoogleSignIn.getClient(appContext, |
| 335 | + new GoogleSignInOptions.Builder(googleOptions) |
| 336 | + .setAccountName(email) |
| 337 | + .build()) |
| 338 | + .silentSignIn() |
| 339 | + .continueWithTask(new Continuation<GoogleSignInAccount, Task<AuthResult>>() { |
| 340 | + @Override |
| 341 | + public Task<AuthResult> then(@NonNull Task<GoogleSignInAccount> task) { |
| 342 | + AuthCredential authCredential = GoogleAuthProvider.getCredential( |
| 343 | + task.getResult().getIdToken(), null); |
| 344 | + return mAuth.signInWithCredential(authCredential); |
| 345 | + } |
| 346 | + }); |
| 347 | + } else { |
| 348 | + return mAuth.signInWithEmailAndPassword(email, password); |
| 349 | + } |
| 350 | + } |
| 351 | + }); |
| 352 | + } |
| 353 | + |
270 | 354 | /**
|
271 | 355 | * Signs the current user out, if one is signed in.
|
272 | 356 | *
|
|
0 commit comments