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

[Wallet] Add reCaptcha verification behind feature flag #5630

Merged
merged 19 commits into from
Oct 31, 2020
Merged

Conversation

gnardini
Copy link
Contributor

Description

Adds reCaptcha implementation behind a feature flag. If KOMENCI is true, after clicking on Start on the VerificationEducationScreen the user will be prompted with a reCaptcha challenge that they'll need to complete before being able to verify. It also adds SafetyNet which is a check for Android devices.

This is missing integration with KomenciKit

Tested

By changing the value of the KOMENCI flag and seeing the captcha flow (captcha code is logged)

Related issues

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I know this file looks weird, it's because of SafetyNet. It depends on react-native-securerandom which doesn't support automatic linking, and when doing it manually it threw an error because this file was missing.

This manual linking is the reason for the changes to the settings.gradle and the Podfile as well.

Copy link
Contributor

Choose a reason for hiding this comment

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

Would love to fork/fix/upstream after wednesday as good citizens of the open source world

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I like doing that sort of stuff too, but the maintainers don't seem very active. The first reason I had to fork was to add support for AndroidX since it was failing for that reason. There's a PR that adds that from almost a year ago: rajivshah3/react-native-google-safetynet#283 which has this message:

Thanks for the PR! I can review and investigate the build failure in a few days when I have some time

(December 2019)

@@ -108,17 +108,26 @@ exports[`TransferConfirmationCard renders correctly for CELO withdrawal transact
</svg>
</View>
</View>
<Text
<View
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This changes are due to the change to the implementation of Expandable. It changes nothing visually, it's just wrapping the Text with a View.

"body": "To make sure your number is really yours, we’re going to send you three messages that will cost about 0.05 cUSD each.\n\nConfirming your number takes about three minutes.",
"title": "Phone Number",
"header": "Connect your phone number",
"body": "Connecting takes about three minutes. To confirm your number, you’ll receive three messages.",
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to keep this text for the fallback version? cc @tarikbellamine

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah good catch. We will want to keep all the old text because both feeless and non-feeless flows will be possible.

@@ -107,6 +107,7 @@
"react-native-fs": "^2.16.6",
"react-native-gesture-handler": "^1.6.1",
"react-native-geth": "https://github.com/celo-org/react-native-geth#5864c09",
"react-native-google-safetynet": "https://github.com/celo-org/react-native-google-safetynet#e698d70",
Copy link
Contributor

Choose a reason for hiding this comment

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

not sure if you created a PR to get this upstreamed - but usually nice to do

@@ -47,6 +60,12 @@ function VerificationEducationScreen({ route, navigation }: Props) {
const numberVerified = useSelector(numberVerifiedSelector)
const partOfOnboarding = !route.params?.hideOnboardingStep

const country = useMemo(() => {
const regionCode = getRegionCode(e164PhoneNumber || '')
const countries = new Countries(i18n.language)
Copy link
Contributor

Choose a reason for hiding this comment

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

this looks like it could be expensive - but just a note that useMemo is not always necessary https://blog.logrocket.com/rethinking-hooks-memoization/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That was a great article, I've specially been guilty of 4. Using useMemo solely for referential equalities in the past.

I didn't benchmark how expensive the call is tbh, but it's iterating and applying transformations over a list, if there are many re-renders it could get expensive I guess. I'll make sure not to abuse the use of useMemo :)

const showCaptcha = async () => {
setIsCaptchaVisible(true)
const safetyNetAttestationResponse = await getSafetyNetAttestation()
Logger.info('SafetyNet attestation complete:', JSON.stringify(safetyNetAttestationResponse))
Copy link
Contributor

Choose a reason for hiding this comment

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

is this response big? do we need to log it all?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is an example response:

{
"apkCertificateDigestSha256": ["+sYXRdwJA3hvue3mKpYrOZ9zSPC7b4mbgzJmdZEDO5w="], 
"apkDigestSha256": "5UVIjg1t6wE5CfIhgRMiXQAmB7PzUpSUyGuirP/qyOs=", 
"apkPackageName": "org.celo.mobile.alfajores.dev", 
"basicIntegrity": true, 
"ctsProfileMatch": true, 
"evaluationType": "BASIC", 
"nonce": "IdJQ46NEBT214jlGZ036i7vZq81j/dBiUOAR6HEM", 
"timestampMs": 1603991278194
}

Probably not all fields are necessary, but I thought they might be useful.

const captchaCode = res?.nativeEvent?.data
if (captchaCode !== 'cancel' && captchaCode !== 'error') {
Logger.info('Captcha code received: ', captchaCode)
// TODO: Add some brief loading indicator and send captcha somewhere before continuing.
Copy link
Contributor

Choose a reason for hiding this comment

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

given the feature flag this is okay, but normally i would request some changes 😛

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, this PR by itself is not super useful, it's just laying the foundation for the next one when this is integrated with KomenciKit :D

{firstButton}
<View style={styles.spacer} />
<TextButton style={styles.doINeedToConfirmButton} onPress={onPressLearnMore}>
{t('verificationEducation.doINeedToConfirm')}
</TextButton>
</ScrollView>
<Modal isVisible={isCaptchaVisible} style={styles.recaptchaModal}>
Copy link
Contributor

Choose a reason for hiding this comment

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

i mentioned this to cal, but we should just be mindful of modals from a perf perspective - can lead to overdraw https://developer.android.com/topic/performance/rendering/overdraw

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, we do use these modals in a bunch a places already, we can address this separately.

</head>
<body>
<div id="captcha" style="height: 100vh;">
<div style="text-align: center; height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center;">
Copy link
Contributor

Choose a reason for hiding this comment

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

could you fix the indents here? (just kidding 😄 )

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Run it through a formatter so it looks nicer :)

</html>`
return (
<WebView
originWhitelist={['*']}
Copy link
Contributor

Choose a reason for hiding this comment

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

<GoogleReCaptcha
siteKey={RECAPTCHA_SITE_KEY}
url={WEB_LINK}
languageCode="en"
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't we want this to be whatever the app language is?

Copy link
Contributor

@tarikbellamine tarikbellamine left a comment

Choose a reason for hiding this comment

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

LGTM.

Please make sure you've thoroughly tested on both OS's and specifically the duplication of the phone number input part.

Copy link
Contributor

@jeanregisser jeanregisser left a comment

Choose a reason for hiding this comment

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

Looking good! 👍 See small comment below.

{firstButton}
<View style={styles.spacer} />
<TextButton style={styles.doINeedToConfirmButton} onPress={onPressLearnMore}>
{t('verificationEducation.doINeedToConfirm')}
</TextButton>
</ScrollView>
<Modal isVisible={isCaptchaVisible} style={styles.recaptchaModal}>
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, we do use these modals in a bunch a places already, we can address this separately.

yarn.lock Outdated
Comment on lines 29321 to 29334
react-native-securerandom@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/react-native-securerandom/-/react-native-securerandom-0.1.1.tgz#f130623a412c338b0afadedbc204c5cbb8bf2070"
integrity sha1-8TBiOkEsM4sK+t7bwgTFy7i/IHA=
dependencies:
base64-js "*"

react-native-securerandom@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/react-native-securerandom/-/react-native-securerandom-1.0.0.tgz#1cff2f727c90c9ec3318b42dbf825a628b53b49b"
integrity sha512-lnhcsWloFzMN/HffyDBlh4VlqdhDH8uxEzUIH3aJPgC1PxV6OKZkvAk409EwsAhcmG/z3yZuVKegKpUr5IM9ug==
dependencies:
base64-js "*"

Copy link
Contributor

@jeanregisser jeanregisser Oct 30, 2020

Choose a reason for hiding this comment

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

We shouldn't add 2 versions of the same depdency here.

@aaronmgdr aaronmgdr removed their request for review October 30, 2020 17:46
@gnardini gnardini added the automerge Have PR merge automatically when checks pass label Oct 30, 2020
@gnardini gnardini removed the automerge Have PR merge automatically when checks pass label Oct 31, 2020
@gnardini gnardini added the automerge Have PR merge automatically when checks pass label Oct 31, 2020
@mergify mergify bot merged commit c6ebf06 into master Oct 31, 2020
@mergify mergify bot deleted the captcha branch October 31, 2020 03:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
automerge Have PR merge automatically when checks pass wallet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants