Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/authenticator/phone validator #5518

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
3a98a38
added checks for country code against the maximum length of number in…
Sep 27, 2024
3d8f70e
added a map of dial codes to number lengths, and check the input phon…
Sep 30, 2024
4173bba
removed files from building example app
Oct 1, 2024
259f4eb
removed files from \sandbox
Oct 1, 2024
8ef9d66
removed files from sandbox
Oct 1, 2024
d765390
updating formatting
Oct 1, 2024
ace278e
chore(common,notifications): update os_detect to 2.0.2 (#5569)
tyllark Oct 18, 2024
6e6edab
chore(dep): update mime version to ^2.0.0 (#5568)
NikaHsn Oct 18, 2024
8222a03
fix(api): Reconnect WebSocket when resuming app from a paused state (…
tyllark Oct 18, 2024
25fe3f0
chore: Cherry Pick Bump version (#5593)
Equartey Oct 23, 2024
0fa2282
chore(infra): Updated micromatch version (#5613)
tyllark Oct 25, 2024
df38424
fix(common): db_common windows sqlite3 collision (#5481)
Equartey Oct 29, 2024
0055e53
feat(auth, authenticator): Add support for Email OTP MFA (#5449) (#5472)
khatruong2009 Oct 31, 2024
76d7ba1
chore(version): Bump version
tyllark Oct 31, 2024
e4b6b68
Chore(infra): update amplify dependencies (#5658)
ekjotmultani Nov 11, 2024
2ee74bb
fix(authenticator): recover from exceptions during reset password flo…
Equartey Nov 13, 2024
bc314f6
fix(common): added a flag to opt out of bundling sqlite3 for windows …
Equartey Nov 25, 2024
371e0a4
fix(storage): Only allow 1 batch to run at a time (#5704)
tyllark Nov 25, 2024
184b10c
added checks for country code against the maximum length of number in…
Sep 27, 2024
0332e29
added a map of dial codes to number lengths, and check the input phon…
Sep 30, 2024
9f0439a
removed files from building example app
Oct 1, 2024
7da3d51
removed files from \sandbox
Oct 1, 2024
3d28992
removed files from sandbox
Oct 1, 2024
9d9498a
updating formatting
Oct 1, 2024
c616675
rewrote functions for better code standards, and rewrote duplicated test
ekjotmultani Jan 4, 2025
6d36e60
Merge branch 'fix/authenticator/phone-validator' of https://github.co…
ekjotmultani Jan 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:amplify_authenticator/src/keys.dart';
import 'package:amplify_authenticator/src/l10n/dial_code_resolver.dart';
import 'package:amplify_authenticator/src/utils/breakpoint.dart';
import 'package:amplify_authenticator/src/utils/dial_code.dart';
import 'package:amplify_authenticator/src/utils/dial_code_to_length.dart';
import 'package:amplify_authenticator/src/widgets/authenticator_input_config.dart';
import 'package:amplify_authenticator/src/widgets/form_field.dart';
import 'package:collection/collection.dart';
Expand Down Expand Up @@ -47,11 +48,20 @@ mixin AuthenticatorPhoneFieldMixin<FieldType extends Enum,
return phoneNumber?.ensureStartsWith('+${state.dialCode.value}');
}

String displayPhoneNumber(String phoneNumber) {
String displayPhoneNumber(String? phoneNumber) {
phoneNumber = phoneNumber ?? '';
final prefix = '+${state.dialCode.value}';
if (phoneNumber.startsWith(prefix)) {
phoneNumber = phoneNumber.substring(prefix.length);
}
// this is to handle the case where the user may errantly input their dial code again in their phone number
// we make sure the user's phone number doesn't naturally just start with their dial code by checking if the number exceeds the maximum phone length of the country's phone number scheme before truncating it
if (phoneNumber.startsWith(prefix.substring(1))) {
if (countryPhoneNumberLengths.containsKey(prefix) &&
phoneNumber.length > countryPhoneNumberLengths[prefix]!) {
phoneNumber = phoneNumber.substring(prefix.length - 1);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor: Can this be rewritten to avoid nested if statements in favor of guard clauses? Something like improves readability:

if (!phoneNumber.startsWith(prefix.substring(1))) {
  return phoneNumber;
}

final prefixLength = countryPhoneNumberLengths[prefix];
if (prefixLength == null || phoneNumber.length <= prefixLength) {
  return phoneNumber;
}

return phoneNumber.substring(prefix.length - 1);

return phoneNumber;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:amplify_authenticator/amplify_authenticator.dart';
import 'package:amplify_authenticator/src/keys.dart';
import 'package:amplify_authenticator/src/models/username_input.dart';
import 'package:amplify_authenticator/src/utils/dial_code_to_length.dart';
import 'package:amplify_authenticator/src/utils/validators.dart';
import 'package:amplify_authenticator/src/widgets/component.dart';
import 'package:amplify_authenticator/src/widgets/form_field.dart';
Expand Down Expand Up @@ -164,6 +165,23 @@ mixin AuthenticatorUsernameField<FieldType extends Enum,
}
}

String displayPhoneNumber(String? phoneNumber) {
phoneNumber = phoneNumber ?? '';
final prefix = '+${state.dialCode.value}';
if (phoneNumber.startsWith(prefix)) {
phoneNumber = phoneNumber.substring(prefix.length);
}
// this is to handle the case where the user may errantly input their dial code again in their phone number
// we make sure the user's phone number doesn't naturally just start with their dial code by checking if the number exceeds the maximum phone length of the country's phone number scheme before truncating it
if (phoneNumber.startsWith(prefix.substring(1))) {
if (countryPhoneNumberLengths.containsKey(prefix) &&
phoneNumber.length > countryPhoneNumberLengths[prefix]!) {
phoneNumber = phoneNumber.substring(prefix.length - 1);
}
}
return phoneNumber;
}

@override
FormFieldValidator<UsernameInput> get validator {
switch (selectedUsernameType) {
Expand All @@ -183,7 +201,7 @@ mixin AuthenticatorUsernameField<FieldType extends Enum,
isOptional: isOptional,
context: context,
inputResolver: stringResolver.inputs,
)(input?.username);
)(displayPhoneNumber(input?.username));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
/// A list of [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1) dial codes mapped to the maximum [possible length](https://en.wikipedia.org/wiki/National_conventions_for_writing_telephone_numbers) of the phone number from that country as an integer
///
///
Comment on lines +1 to +5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: I assume this is coming from libphonenumber... Can you ensure this is has the proper license & attribution for us to use?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this comes by scraping their metadata, it looks like they have an Apache 2.0 License. Is that ok for us to use?

Map<String, int> countryPhoneNumberLengths = {
'+1': 10, // United States, Canada, and other NANP countries
'+7': 10, // Russia, Kazakhstan
'+20': 10, // Egypt
'+27': 9, // South Africa
'+30': 10, // Greece
'+31': 9, // Netherlands
'+32': 9, // Belgium
'+33': 9, // France
'+34': 9, // Spain
'+36': 9, // Hungary
'+39': 10, // Italy
'+40': 9, // Romania
'+44': 10, // United Kingdom
'+45': 8, // Denmark
'+46': 9, // Sweden
'+47': 8, // Norway
'+48': 9, // Poland
'+49': 11, // Germany
'+51': 9, // Peru
'+52': 10, // Mexico
'+53': 8, // Cuba
'+54': 10, // Argentina
'+55': 11, // Brazil
'+56': 9, // Chile
'+57': 10, // Colombia
'+58': 10, // Venezuela
'+60': 10, // Malaysia
'+61': 9, // Australia
'+62': 11, // Indonesia
'+63': 10, // Philippines
'+64': 9, // New Zealand
'+65': 8, // Singapore
'+66': 9, // Thailand
'+81': 10, // Japan
'+82': 10, // South Korea
'+84': 10, // Vietnam
'+86': 11, // China
'+90': 11, // Turkey
'+91': 10, // India
'+92': 10, // Pakistan
'+93': 9, // Afghanistan
'+94': 10, // Sri Lanka
'+95': 9, // Myanmar
'+98': 10, // Iran
'+211': 9, // South Sudan
'+212': 9, // Morocco
'+213': 9, // Algeria
'+216': 8, // Tunisia
'+218': 10, // Libya
'+220': 7, // Gambia
'+221': 9, // Senegal
'+222': 9, // Mauritania
'+223': 8, // Mali
'+224': 9, // Guinea
'+225': 10, // Ivory Coast
'+226': 8, // Burkina Faso
'+227': 8, // Niger
'+228': 8, // Togo
'+229': 8, // Benin
'+230': 7, // Mauritius
'+231': 9, // Liberia
'+232': 8, // Sierra Leone
'+233': 9, // Ghana
'+234': 10, // Nigeria
'+235': 8, // Chad
'+236': 8, // Central African Republic
'+237': 9, // Cameroon
'+238': 7, // Cape Verde
'+239': 7, // São Tomé and Príncipe
'+240': 9, // Equatorial Guinea
'+241': 9, // Gabon
'+242': 9, // Republic of the Congo
'+243': 9, // DR Congo
'+244': 9, // Angola
'+245': 7, // Guinea-Bissau
'+248': 7, // Seychelles
'+249': 9, // Sudan
'+250': 9, // Rwanda
'+251': 9, // Ethiopia
'+252': 8, // Somalia
'+253': 8, // Djibouti
'+254': 10, // Kenya
'+255': 9, // Tanzania
'+256': 9, // Uganda
'+257': 8, // Burundi
'+258': 9, // Mozambique
'+260': 9, // Zambia
'+261': 9, // Madagascar
'+262': 9, // Réunion
'+263': 9, // Zimbabwe
'+264': 9, // Namibia
'+265': 9, // Malawi
'+266': 8, // Lesotho
'+267': 8, // Botswana
'+268': 8, // Eswatini (Swaziland)
'+269': 7, // Comoros
'+290': 4, // Saint Helena
'+291': 7, // Eritrea
'+297': 7, // Aruba
'+298': 6, // Faroe Islands
'+299': 6, // Greenland
'+350': 8, // Gibraltar
'+351': 9, // Portugal
'+352': 9, // Luxembourg
'+353': 9, // Ireland
'+354': 7, // Iceland
'+355': 9, // Albania
'+356': 8, // Malta
'+357': 8, // Cyprus
'+358': 10, // Finland
'+359': 9, // Bulgaria
'+370': 8, // Lithuania
'+371': 8, // Latvia
'+372': 8, // Estonia
'+373': 8, // Moldova
'+374': 8, // Armenia
'+375': 9, // Belarus
'+376': 6, // Andorra
'+377': 8, // Monaco
'+378': 10, // San Marino
'+380': 9, // Ukraine
'+381': 9, // Serbia
'+382': 9, // Montenegro
'+385': 9, // Croatia
'+386': 9, // Slovenia
'+387': 8, // Bosnia and Herzegovina
'+389': 8, // North Macedonia
'+420': 9, // Czech Republic
'+421': 9, // Slovakia
'+423': 7, // Liechtenstein
'+500': 5, // Falkland Islands
'+501': 7, // Belize
'+502': 8, // Guatemala
'+503': 8, // El Salvador
'+504': 8, // Honduras
'+505': 8, // Nicaragua
'+506': 8, // Costa Rica
'+507': 7, // Panama
'+509': 8, // Haiti
'+590': 9, // Guadeloupe
'+591': 8, // Bolivia
'+592': 7, // Guyana
'+593': 9, // Ecuador
'+594': 9, // French Guiana
'+595': 9, // Paraguay
'+596': 9, // Martinique
'+597': 7, // Suriname
'+598': 9, // Uruguay
'+670': 7, // East Timor
'+672': 6, // Australian External Territories
'+673': 7, // Brunei
'+674': 7, // Nauru
'+675': 8, // Papua New Guinea
'+676': 5, // Tonga
'+677': 7, // Solomon Islands
'+678': 7, // Vanuatu
'+679': 7, // Fiji
'+680': 7, // Palau
'+681': 6, // Wallis and Futuna
'+682': 5, // Cook Islands
'+683': 4, // Niue
'+685': 7, // Samoa
'+686': 8, // Kiribati
'+687': 6, // New Caledonia
'+688': 5, // Tuvalu
'+689': 6, // French Polynesia
'+690': 4, // Tokelau
'+691': 7, // Micronesia
'+692': 7, // Marshall Islands
'+850': 10, // North Korea
'+852': 8, // Hong Kong
'+853': 8, // Macau
'+855': 9, // Cambodia
'+856': 9, // Laos
'+880': 10, // Bangladesh
'+886': 9, // Taiwan
'+960': 7, // Maldives
'+961': 8, // Lebanon
'+962': 9, // Jordan
'+963': 9, // Syria
'+964': 10, // Iraq
'+965': 8, // Kuwait
'+966': 9, // Saudi Arabia
'+967': 9, // Yemen
'+968': 8, // Oman
'+970': 9, // Palestine
'+971': 9, // United Arab Emirates
'+972': 9, // Israel
'+973': 8, // Bahrain
'+974': 8, // Qatar
'+975': 8, // Bhutan
'+976': 8, // Mongolia
'+977': 10, // Nepal
'+992': 9, // Tajikistan
'+993': 8, // Turkmenistan
'+994': 9, // Azerbaijan
'+995': 9, // Georgia
'+996': 9, // Kyrgyzstan
'+998': 9, // Uzbekistan
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import 'package:flutter/material.dart';
*/
final usernameRegex = RegExp(r'^\S+$');
final emailRegex = RegExp(r'^\S+@\S+$');
final phoneNumberRegex = RegExp(r'^\+\d+$');
final phoneNumberRegex = RegExp(r'^\d+$');
final _codeRegex = RegExp(r'^\d{6}$');
final _uppercase = RegExp(r'[A-Z]');
final _lowercase = RegExp(r'[a-z]');
Expand Down Expand Up @@ -154,8 +154,8 @@ FormFieldValidator<String> validatePhoneNumber({
InputResolverKey.phoneNumberEmpty,
);
}
phoneNumber = phoneNumber.trim();
if (!phoneNumberRegex.hasMatch(phoneNumber)) {
final formattedNumber = phoneNumber.trim();
if (!phoneNumberRegex.hasMatch(formattedNumber)) {
return inputResolver.resolve(context, InputResolverKey.phoneNumberFormat);
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ class _ConfirmSignInPhoneFieldState extends _ConfirmSignInTextFieldState
@override
FormFieldValidator<String> get validator {
return (phoneNumber) {
phoneNumber = formatPhoneNumber(phoneNumber);
phoneNumber = displayPhoneNumber(phoneNumber);
return validatePhoneNumber(
inputResolver: stringResolver.inputs,
context: context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,12 @@ class _AuthenticatorPhoneFieldState<FieldType extends Enum>
@override
FormFieldValidator<String> get validator {
return (String? phoneNumber) {
phoneNumber = formatPhoneNumber(phoneNumber);
final validator = widget.validator;
if (validator != null) {
phoneNumber = formatPhoneNumber(phoneNumber);
return validator(phoneNumber);
}
phoneNumber = displayPhoneNumber(phoneNumber);
return validatePhoneNumber(
inputResolver: stringResolver.inputs,
context: context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ class _SignUpPhoneFieldState extends _SignUpTextFieldState
@override
FormFieldValidator<String> get validator {
return (phoneNumber) {
phoneNumber = formatPhoneNumber(phoneNumber);
phoneNumber = displayPhoneNumber(phoneNumber);
return validatePhoneNumber(
inputResolver: stringResolver.inputs,
context: context,
Expand Down
Loading
Loading