Skip to content

Commit fd99883

Browse files
lsiracsamtstern
authored andcommitted
Include/exclude countries from the country selector list in phone authentication (#1315)
1 parent 204f65f commit fd99883

File tree

7 files changed

+361
-271
lines changed

7 files changed

+361
-271
lines changed

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

Lines changed: 141 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
import java.util.HashSet;
7878
import java.util.IdentityHashMap;
7979
import java.util.List;
80+
import java.util.Locale;
8081
import java.util.Set;
8182

8283
/**
@@ -214,9 +215,9 @@ public static int getDefaultTheme() {
214215
* Signs the user in without any UI if possible. If this operation fails, you can safely start a
215216
* UI-based sign-in flow knowing it is required.
216217
*
217-
* @param context requesting the user be signed in
218-
* @param configs to use for silent sign in. Only Google and email are currently
219-
* supported, the rest will be ignored.
218+
* @param context requesting the user be signed in
219+
* @param configs to use for silent sign in. Only Google and email are currently supported, the
220+
* rest will be ignored.
220221
* @return a task which indicates whether or not the user was successfully signed in.
221222
*/
222223
@NonNull
@@ -643,10 +644,140 @@ public PhoneBuilder setDefaultCountryIso(@NonNull String iso) {
643644
throw new IllegalStateException("Invalid country iso: " + iso);
644645
}
645646

646-
getParams().putString(ExtraConstants.COUNTRY_ISO, iso);
647+
getParams().putString(ExtraConstants.COUNTRY_ISO,
648+
iso.toUpperCase(Locale.getDefault()));
649+
650+
return this;
651+
}
652+
653+
654+
/**
655+
* Sets the country codes available in the country code selector for phone
656+
* authentication. Takes as input a List of both country isos and codes.
657+
* This is not to be called with
658+
* {@link #setBlacklistedCountries(List<String>)}.
659+
* If both are called, an exception will be thrown.
660+
* <p>
661+
* Inputting an e-164 country code (e.g. '+1') will include all countries with
662+
* +1 as its code.
663+
* Example input: {'+52', 'us'}
664+
* For a list of country iso or codes, see Alpha-2 isos here:
665+
* https://en.wikipedia.org/wiki/ISO_3166-1
666+
* and e-164 codes here: https://en.wikipedia.org/wiki/List_of_country_calling_codes
667+
*
668+
* @param whitelistedCountries a case insensitive list of country codes and/or
669+
* isos to be whitelisted
670+
*/
671+
public PhoneBuilder setWhitelistedCountries(
672+
@NonNull List<String> whitelistedCountries) {
673+
if (getParams().containsKey(ExtraConstants.BLACKLISTED_COUNTRIES)) {
674+
throw new RuntimeException(
675+
"You can either whitelist or blacklist country codes for phone " +
676+
"authentication.");
677+
}
678+
addCountriesToBundle(whitelistedCountries, ExtraConstants.WHITELISTED_COUNTRIES);
679+
return this;
680+
}
647681

682+
/**
683+
* Sets the countries to be removed from the country code selector for phone
684+
* authentication. Takes as input a List of both country isos and codes.
685+
* This is not to be called with
686+
* {@link #setWhitelistedCountries(List<String>)}.
687+
* If both are called, an exception will be thrown.
688+
* <p>
689+
* Inputting an e-164 country code (e.g. '+1') will include all countries with
690+
* +1 as its code.
691+
* Example input: {'+52', 'us'}
692+
* For a list of country iso or codes, see Alpha-2 codes here:
693+
* https://en.wikipedia.org/wiki/ISO_3166-1
694+
* and e-164 codes here: https://en.wikipedia.org/wiki/List_of_country_calling_codes
695+
* @param blacklistedCountries a case insensitive list of country codes and/or isos
696+
* to be blacklisted
697+
*/
698+
public PhoneBuilder setBlacklistedCountries(
699+
@NonNull List<String> blacklistedCountries) {
700+
if (getParams().containsKey(ExtraConstants.WHITELISTED_COUNTRIES)) {
701+
throw new RuntimeException(
702+
"You can either whitelist or blacklist country codes for phone " +
703+
"authentication.");
704+
}
705+
addCountriesToBundle(blacklistedCountries, ExtraConstants.BLACKLISTED_COUNTRIES);
648706
return this;
649707
}
708+
709+
@Override
710+
public IdpConfig build() {
711+
validateInputs();
712+
return super.build();
713+
}
714+
715+
private void addCountriesToBundle(List<String> CountryIsos, String CountryIsoType) {
716+
ArrayList<String> uppercaseCodes = new ArrayList<>();
717+
for (String code : CountryIsos) {
718+
uppercaseCodes.add(code.toUpperCase(Locale.getDefault()));
719+
}
720+
721+
getParams().putStringArrayList(CountryIsoType, uppercaseCodes);
722+
}
723+
724+
private void validateInputs() {
725+
List<String> whitelistedCountries = getParams().getStringArrayList(
726+
ExtraConstants.WHITELISTED_COUNTRIES);
727+
List<String> blacklistedCountries = getParams().getStringArrayList(
728+
ExtraConstants.BLACKLISTED_COUNTRIES);
729+
730+
if (whitelistedCountries != null &&
731+
blacklistedCountries != null) {
732+
throw new RuntimeException(
733+
"You can either whitelist or blacklist country codes for phone " +
734+
"authentication.");
735+
} else if (whitelistedCountries != null) {
736+
validateCountries(whitelistedCountries);
737+
validateDefaultCountryIso(whitelistedCountries, true);
738+
739+
} else if (blacklistedCountries != null) {
740+
validateCountries(blacklistedCountries);
741+
validateDefaultCountryIso(blacklistedCountries, false);
742+
}
743+
}
744+
745+
private void validateCountries(List<String> codes) {
746+
for (String code : codes) {
747+
if (!PhoneNumberUtils.isValidIso(code) && !PhoneNumberUtils.isValid(code)) {
748+
throw new RuntimeException("Invalid input: You must provide a valid " +
749+
"country iso (alpha-2) or code (e-164). e.g. 'us' or '+1'.");
750+
}
751+
}
752+
}
753+
754+
private void validateDefaultCountryIso(List<String> codes, boolean whitelisted) {
755+
if (getParams().containsKey(ExtraConstants.COUNTRY_ISO) && codes != null) {
756+
String defaultIso = getParams().getString(ExtraConstants.COUNTRY_ISO);
757+
boolean containsIso = containsCountryIso(codes, defaultIso);
758+
if (!containsIso && whitelisted || containsIso && !whitelisted) {
759+
throw new RuntimeException("Invalid default country iso. Make sure it " +
760+
"is either part of the whitelisted list or that you " +
761+
"haven't blacklisted it.");
762+
}
763+
}
764+
}
765+
766+
private boolean containsCountryIso(List<String> codes, String iso) {
767+
for (String code : codes) {
768+
if (PhoneNumberUtils.isValidIso(code)) {
769+
if (code.equals(iso)) {
770+
return true;
771+
}
772+
} else {
773+
List<String> isos = PhoneNumberUtils.getCountryIsosFromCountryCode(code);
774+
if (isos.contains(iso)) {
775+
return true;
776+
}
777+
}
778+
}
779+
return false;
780+
}
650781
}
651782

652783
/**
@@ -679,8 +810,8 @@ public GoogleBuilder setScopes(@NonNull List<String> scopes) {
679810
}
680811

681812
/**
682-
* Set the {@link GoogleSignInOptions} to be used for Google sign-in. Standard options
683-
* like requesting the user's email will automatically be added.
813+
* Set the {@link GoogleSignInOptions} to be used for Google sign-in. Standard
814+
* options like requesting the user's email will automatically be added.
684815
*
685816
* @param options sign-in options
686817
*/
@@ -784,8 +915,8 @@ private abstract class AuthIntentBuilder<T extends AuthIntentBuilder> {
784915
boolean mEnableHints = true;
785916

786917
/**
787-
* Specifies the theme to use for the application flow. If no theme is specified, a default
788-
* theme will be used.
918+
* Specifies the theme to use for the application flow. If no theme is specified, a
919+
* default theme will be used.
789920
*/
790921
@NonNull
791922
public T setTheme(@StyleRes int theme) {
@@ -825,8 +956,8 @@ public T setPrivacyPolicyUrl(@Nullable String privacyPolicyUrl) {
825956
}
826957

827958
/**
828-
* Specified the set of supported authentication providers. At least one provider must be
829-
* specified. There may only be one instance of each provider.
959+
* Specified the set of supported authentication providers. At least one provider must
960+
* be specified. There may only be one instance of each provider.
830961
* <p>
831962
* <p>If no providers are explicitly specified by calling this method, then the email
832963
* provider is the default supported provider.

0 commit comments

Comments
 (0)