React Native
...
Cloud Functions
Autenticazione OTP in React Native con Parse Cloud Code
12 min
autenticazione otp per react native utilizzando cloud functions introduzione in questa guida, imparerai come utilizzare una funzione di cloud code di parse per integrare l'api twilio verify in un'app react native per abilitare una funzionalità di accesso otp le funzioni di cloud code sono il posto perfetto per questo tipo di operazioni poiché ti consentono di gestire dati sensibili e utilizzare altre api al di fuori della tua applicazione in questa guida verificherai anche come implementare un componente react native utilizzando l'integrazione otp, migliorando il nostro precedente esempio di guida sulla verifica dell'email dell'utente in qualsiasi momento, puoi accedere al progetto android completo costruito con questo tutorial nei nostri repository github repository di esempio kotlin repository di esempio java requisiti per completare questo tutorial, avrai bisogno di un'app react native creata e collegata a back4app comprendere come distribuire una funzione cloud su back4app un account attivo su twilio, puoi crearne uno di prova gratuito qui un account attivo su sendgrid, puoi crearne uno di prova gratuito qui obiettivo integrare l'api twilio verify utilizzando le funzioni del codice cloud di parse su back4app e utilizzarla in un'app react native 1 configurazione di twilio verify twilio è un fornitore di servizi di token 2fa e otp ben noto, utilizzato da un'ampia gamma di aziende al giorno d'oggi l'api verify è un insieme di api semplificate per aiutare gli sviluppatori a verificare telefoni, email e a eseguire accessi senza password senza problemi in questa guida, utilizzerai i metodi di verifica sms e email per abilitare la tua applicazione a avere una funzionalità otp seguiremo la documentazione ufficiale di verify docs https //www twilio com/docs/verify/api , quindi fai riferimento ad essa se qualche passaggio ti risulta confuso dopo aver creato i tuoi account twilio e sendgrid (sendgrid è necessario per inviare email automatiche contenenti i tuoi token utente), annota i seguenti identificatori, che possono essere recuperati dalla dashboard di ciascun servizio sid dell'account twilio e token di autenticazione; id di sendgrid e un id di template email semplice ora, crea un nuovo servizio di verifica in twilio verify dashboard https //www twilio com/console/verify/dashboard , che è un insieme di configurazioni che gestirà le nostre richieste e verifiche otp assicurati di annotare il tuo sid del servizio qui se vuoi, puoi anche abilitare l'invio di codici via email aggiungendo le tue chiavi sendgrid creando una nuova integrazione email all'interno del servizio di verifica dashboard https //www twilio com/docs/verify/email questo è tutto, tutta la configurazione è completata e possiamo ora procedere a creare le nostre funzioni cloud code 2 integrazione tramite funzioni cloud code come discusso in precedenza, utilizzare le funzioni cloud code nella tua applicazione consente una grande flessibilità nel tuo codice, rendendo possibile staccare metodi riutilizzabili dalla tua app e controllarne meglio il comportamento puoi controllare o rivedere come usarli in la nostra guida introduttiva alle funzioni cloud https //www back4app com/docs/get started/cloud functions creiamo la nostra prima funzione cloud chiamata requestotp requestotp , in cui verrà creato un otp e inviato all'utente attraverso il metodo scelto la funzione deve ricevere due parametri, userdata userdata contenente un'email o un numero di telefono e v erificationtype erificationtype , specificando quale metodo di verifica utilizzare, email email o sms sms ecco il codice della funzione 1 // define twilio keys and require the library helper 2 const accountsid = 'your twilio account sid here'; 3 const authtoken = 'your twilio auth token here'; 4 const client = require('twilio')(accountsid, authtoken); 5	 6 // request otp 7 parse cloud define('requestotp', async (request) => { 8 const userdata = request params userdata; 9 const verificationtype = request params verificationtype; 10 let verification request = await client verify 11 services('your twilio verify service id here') 12 verifications create({ to userdata, channel verificationtype }); 13 return { status verification request status, error '' }; 14 }); nota che in cima abbiamo definito le nostre chiavi api twilio e abbiamo anche importato la libreria helper l'implementazione del server parse di back4app ci fornisce accesso alla libreria twilio di default, quindi non è necessario installarla sul tuo server la seconda e ultima funzione cloud si chiama verifyotp verifyotp , verifica il token dell'utente in twilio’s verify e lo accede automaticamente, creando una sessione e restituendo il suo id alla tua applicazione, in modo da poter accedere senza password da lì ci sono quattro parametri richiesti, i primi due sono gli stessi della funzione precedente, con l'aggiunta di usertoken usertoken , contenente il token di verifica informato, e anche userinstallationid userinstallationid , che sarà spiegato più avanti 1 // since we need in uuid v4 id for creating a new session, this function 2 // mocks the creation of one without the need to import the `uuidv4` module 3 // for a more robust solution, consider using the uuid module, which uses 4 // higher quality rng apis 5 // adapted from https //stackoverflow\ com/a/2117523 6 function uuidv4() { 7 return 'xxxxxxxx xxxx 4xxx yxxx xxxxxxxxxxxx' replace(/\[xy]/g, function (c) { 8 var r = (math random() 16) | 0, 9 v = c == 'x' ? r (r & 0x3) | 0x8; 10 return v tostring(16); 11 }); 12 } 13	 14 // verify otp 15 parse cloud define('verifyotp', async (request) => { 16 const { userdata, verificationtype, usertoken, userinstallationid } = 17 request params; 18 let verification check = await client verify 19 services('your twilio verify service id here') 20 verificationchecks create({ to userdata, code usertoken }); 21 // status can be 'approved' if correct or 'pending' if incorrect 22 if (verification check status === 'approved') { 23 try { 24 // get user to login 25 let user = null; 26 if (verificationtype === 'sms') { 27 user = await new parse query(parse user) 28 equalto('phonenumber', userdata) 29 first({ usemasterkey true }); 30 } else { 31 user = await new parse query(parse user) 32 equalto('email', userdata) 33 first({ usemasterkey true }); 34 } 35 // create new session for login use in 36 // manually create session (without using parse session because of it's update restrictions) 37 // adapted from https //stackoverflow\ com/a/67432715 38 let session = new parse object(' session', { 39 user user, 40 installationid userinstallationid, 41 sessiontoken `r ${uuidv4()}`, 42 }); 43 session = await session save(undefined, { usemasterkey true }); 44 return { sessionid session get('sessiontoken') }; 45 } catch (error) { 46 console log(error); 47 return { error `${error}` }; 48 } 49 } 50 return { error 'could not validate your token or account! try again!' }; 51 }); assicurati di distribuire queste funzioni nel tuo parse server prima di passare al passaggio successivo 3 creazione di una funzione otp in react native utilizziamo ora lo stesso esempio di progetto dalla verifica email utente guida https //www back4app com/docs/react native/parse sdk/working with users/react native email verification come base e apportiamo alcune modifiche per abilitare la nuova funzionalità otp ti consigliamo di scaricare l'esempio di progetto e configurarlo prima di continuare con la guida per prima cosa, per consentire agli utenti di accedere utilizzando il proprio numero di telefono, aggiungi un nuovo campo di input e aggiungi il valore al metodo di salvataggio della registrazione dell'utente nel userregistration js userregistration js (o userregistration tsx userregistration tsx ) file javascript 1 import react, {usestate} from 'react'; 2 import { 3 alert, 4 image, 5 text, 6 textinput, 7 touchableopacity, 8 view, 9 } from 'react native'; 10 import parse from 'parse/react native'; 11 import {usenavigation} from '@react navigation/native'; 12 import {stackactions} from '@react navigation/native'; 13 import styles from ' /styles'; 14	 15 export const userregistration = () => { 16 const navigation = usenavigation(); 17	 18 const \[username, setusername] = usestate(''); 19 const \[password, setpassword] = usestate(''); 20 const \[email, setemail] = usestate(''); 21 const \[phonenumber, setphonenumber] = usestate(''); 22	 23 const dousersignup = async function () { 24 // note that this values come from state variables that we've declared before 25 const usernamevalue = username; 26 const passwordvalue = password; 27 const emailvalue = email; 28 const phonenumbervalue = phonenumber; 29 try { 30 // since the signup method returns a promise, we need to call it using await 31 // note that now you are setting the user email value as well 32 let createduser = await parse user signup(usernamevalue, passwordvalue, { 33 email emailvalue, 34 phonenumber phonenumbervalue, 35 }); 36	 37 // parse user signup returns the already created parseuser object if successful 38 alert alert( 39 'success!', 40 `user ${createduser get( 41 'username', 42 )} was successfully created! verify your email to login`, 43 ); 44 // since email verification is now required, make sure to log out 45 // the new user, so any session created is cleared and the user can 46 // safely log in again after verifying 47 await parse user logout(); 48 // go back to the login page 49 navigation dispatch(stackactions poptotop()); 50 return true; 51 } catch (error) { 52 // signup can fail if any parameter is blank or failed an uniqueness check on the server 53 alert alert('error!', error message); 54 return false; 55 } 56 }; 57	 58 return ( 59 \<view style={styles login wrapper}> 60 \<view style={styles form}> 61 \<textinput 62 style={styles form input} 63 value={username} 64 placeholder={'username'} 65 onchangetext={(text) => setusername(text)} 66 autocapitalize={'none'} 67 keyboardtype={'email address'} 68 /> 69 \<textinput 70 style={styles form input} 71 value={email} 72 placeholder={'email'} 73 onchangetext={(text) => setemail(text)} 74 autocapitalize={'none'} 75 keyboardtype={'email address'} 76 /> 77 \<textinput 78 style={styles form input} 79 value={phonenumber} 80 placeholder={'phone (international format +15017122661)'} 81 onchangetext={(text) => setphonenumber(text)} 82 autocapitalize={'none'} 83 keyboardtype={'phone pad'} 84 /> 85 \<textinput 86 style={styles form input} 87 value={password} 88 placeholder={'password'} 89 securetextentry 90 onchangetext={(text) => setpassword(text)} 91 /> 92 \<touchableopacity onpress={() => dousersignup()}> 93 \<view style={styles button}> 94 \<text style={styles button label}>{'sign up'}\</text> 95 \</view> 96 \</touchableopacity> 97 \</view> 98 \<view style={styles login social}> 99 \<view style={styles login social separator}> 100 \<view style={styles login social separator line} /> 101 \<text style={styles login social separator text}>{'or'}\</text> 102 \<view style={styles login social separator line} /> 103 \</view> 104 \<view style={styles login social buttons}> 105 \<touchableopacity> 106 \<view 107 style={\[ 108 styles login social button, 109 styles login social facebook, 110 ]}> 111 \<image 112 style={styles login social icon} 113 source={require(' /assets/icon facebook png')} 114 /> 115 \</view> 116 \</touchableopacity> 117 \<touchableopacity> 118 \<view style={styles login social button}> 119 \<image 120 style={styles login social icon} 121 source={require(' /assets/icon google png')} 122 /> 123 \</view> 124 \</touchableopacity> 125 \<touchableopacity> 126 \<view style={styles login social button}> 127 \<image 128 style={styles login social icon} 129 source={require(' /assets/icon apple png')} 130 /> 131 \</view> 132 \</touchableopacity> 133 \</view> 134 \</view> 135 <> 136 \<touchableopacity onpress={() => navigation navigate('login')}> 137 \<text style={styles login footer text}> 138 {'already have an account? '} 139 \<text style={styles login footer link}>{'log in'}\</text> 140 \</text> 141 \</touchableopacity> 142 \</> 143 \</view> 144 ); 145 };1 import react, {fc, reactelement, usestate} from 'react'; 2 import { 3 alert, 4 image, 5 text, 6 textinput, 7 touchableopacity, 8 view, 9 } from 'react native'; 10 import parse from 'parse/react native'; 11 import {usenavigation} from '@react navigation/native'; 12 import {stackactions} from '@react navigation/native'; 13 import styles from ' /styles'; 14	 15 export const userregistration fc<{}> = ({}) reactelement => { 16 const navigation = usenavigation(); 17	 18 const \[username, setusername] = usestate(''); 19 const \[password, setpassword] = usestate(''); 20 const \[email, setemail] = usestate(''); 21 const \[phonenumber, setphonenumber] = usestate(''); 22	 23 const dousersignup = async function () promise\<boolean> { 24 // note that this values come from state variables that we've declared before 25 const usernamevalue string = username; 26 const passwordvalue string = password; 27 const emailvalue string = email; 28 const phonenumbervalue string = phonenumber; 29 try { 30 // since the signup method returns a promise, we need to call it using await 31 // note that now you are setting the user email value as well 32 let createduser = await parse user signup(usernamevalue, passwordvalue, { 33 email emailvalue, 34 phonenumber phonenumbervalue, 35 }); 36	 37 // parse user signup returns the already created parseuser object if successful 38 alert alert( 39 'success!', 40 `user ${createduser get( 41 'username', 42 )} was successfully created! verify your email to login`, 43 ); 44 // since email verification is now required, make sure to log out 45 // the new user, so any session created is cleared and the user can 46 // safely log in again after verifying 47 await parse user logout(); 48 // go back to the login page 49 navigation dispatch(stackactions poptotop()); 50 return true; 51 } catch (error object) { 52 // signup can fail if any parameter is blank or failed an uniqueness check on the server 53 alert alert('error!', error message); 54 return false; 55 } 56 }; 57	 58 return ( 59 \<view style={styles login wrapper}> 60 \<view style={styles form}> 61 \<textinput 62 style={styles form input} 63 value={username} 64 placeholder={'username'} 65 onchangetext={(text) => setusername(text)} 66 autocapitalize={'none'} 67 keyboardtype={'email address'} 68 /> 69 \<textinput 70 style={styles form input} 71 value={email} 72 placeholder={'email'} 73 onchangetext={(text) => setemail(text)} 74 autocapitalize={'none'} 75 keyboardtype={'email address'} 76 /> 77 \<textinput 78 style={styles form input} 79 value={phonenumber} 80 placeholder={'phone (international format +15017122661)'} 81 onchangetext={(text) => setphonenumber(text)} 82 autocapitalize={'none'} 83 keyboardtype={'phone pad'} 84 /> 85 \<textinput 86 style={styles form input} 87 value={password} 88 placeholder={'password'} 89 securetextentry 90 onchangetext={(text) => setpassword(text)} 91 /> 92 \<touchableopacity onpress={() => dousersignup()}> 93 \<view style={styles button}> 94 \<text style={styles button label}>{'sign up'}\</text> 95 \</view> 96 \</touchableopacity> 97 \</view> 98 \<view style={styles login social}> 99 \<view style={styles login social separator}> 100 \<view style={styles login social separator line} /> 101 \<text style={styles login social separator text}>{'or'}\</text> 102 \<view style={styles login social separator line} /> 103 \</view> 104 \<view style={styles login social buttons}> 105 \<touchableopacity> 106 \<view 107 style={\[ 108 styles login social button, 109 styles login social facebook, 110 ]}> 111 \<image 112 style={styles login social icon} 113 source={require(' /assets/icon facebook png')} 114 /> 115 \</view> 116 \</touchableopacity> 117 \<touchableopacity> 118 \<view style={styles login social button}> 119 \<image 120 style={styles login social icon} 121 source={require(' /assets/icon google png')} 122 /> 123 \</view> 124 \</touchableopacity> 125 \<touchableopacity> 126 \<view style={styles login social button}> 127 \<image 128 style={styles login social icon} 129 source={require(' /assets/icon apple png')} 130 /> 131 \</view> 132 \</touchableopacity> 133 \</view> 134 \</view> 135 <> 136 \<touchableopacity onpress={() => navigation navigate('login')}> 137 \<text style={styles login footer text}> 138 {'already have an account? '} 139 \<text style={styles login footer link}>{'log in'}\</text> 140 \</text> 141 \</touchableopacity> 142 \</> 143 \</view> 144 ); 145 }; creiamo ora un nuovo file contenente il nuovo userotp userotp schermo, che gestirà tutti i processi otp lo schermo avrà due campi di input, il primo per consentire all'utente di fornire i mezzi per ricevere l'otp (indirizzo email o numero di telefono) l'altro campo di input, nascosto prima di inviare la richiesta otp, conterrà il token ricevuto dall'utente ecco il codice completo di userotp js userotp js (o userotp tsx userotp tsx ) javascript 1 import react, {usestate} from 'react'; 2 import {alert, text, textinput, touchableopacity, view} from 'react native'; 3 import parse from 'parse/react native'; 4 import {usenavigation} from '@react navigation/native'; 5 import styles from ' /styles'; 6	 7 export const userotp = () => { 8 const navigation = usenavigation(); 9	 10 const \[userdata, setuserdata] = usestate(''); 11 const \[usertoken, setusertoken] = usestate(''); 12 const \[tokenrequested, settokenrequested] = usestate(false); 13	 14 const requestotp = async function () { 15 // note that this values come from state variables that we've declared before 16 const userdatavalue = userdata; 17 // check if value is an email if it contains @ note that in a real 18 // app you need a much better validator for this field 19 const verificationtype = 20 userdatavalue includes('@') === true ? 'email' 'sms'; 21 // we need to call it using await 22 try { 23 await parse cloud run('requestotp', { 24 userdata userdatavalue, 25 verificationtype verificationtype, 26 }); 27 // show token input field 28 settokenrequested(true); 29 alert alert('success!', `token requested via ${verificationtype}!`); 30 return true; 31 } catch (error) { 32 alert alert('error!', error message); 33 return false; 34 } 35 }; 36	 37 const verifyotp = async function () { 38 // note that this values come from state variables that we've declared before 39 const userdatavalue = userdata; 40 const usertokenvalue = usertoken; 41 // check if value is an email if it contains @ note that in a real 42 // app you need a much better validator for this field 43 const verificationtype = 44 userdatavalue includes('@') === true ? 'email' 'sms'; 45 // we need the installation id to allow cloud code to create 46 // a new session and login user without password 47 const parseinstallationid = await parse getinstallationid(); 48 // we need to call it using await 49 try { 50 // verify otp, if successful, returns a sessionid 51 let response = await parse cloud run('verifyotp', { 52 userdata userdatavalue, 53 verificationtype verificationtype, 54 usertoken usertokenvalue, 55 parseinstallationid parseinstallationid, 56 }); 57 if (response sessionid !== undefined) { 58 // use generated sessionid to become a user, 59 // logging in without needing to inform password and username 60 await parse user become(response sessionid); 61 const loggedinuser= await parse user currentasync(); 62 alert alert( 63 'success!', 64 `user ${loggedinuser get('username')} has successfully signed in!`, 65 ); 66 // navigation navigate takes the user to the home screen 67 navigation navigate('home'); 68 return true; 69 } else { 70 throw response; 71 } 72 } catch (error) { 73 alert alert('error!', error message); 74 return false; 75 } 76 }; 77	 78 return ( 79 \<view style={styles login wrapper}> 80 {tokenrequested === false ? ( 81 \<view style={styles form}> 82 \<textinput 83 style={styles form input} 84 value={userdata} 85 placeholder={'email or mobile phone number'} 86 onchangetext={(text) => setuserdata(text)} 87 autocapitalize={'none'} 88 keyboardtype={'email address'} 89 /> 90 \<touchableopacity onpress={() => requestotp()}> 91 \<view style={styles button}> 92 \<text style={styles button label}>{'request otp'}\</text> 93 \</view> 94 \</touchableopacity> 95 \</view> 96 ) ( 97 \<view style={styles form}> 98 \<text>{'inform the received token to proceed'}\</text> 99 \<textinput 100 style={styles form input} 101 value={usertoken} 102 placeholder={'token (6 digits)'} 103 onchangetext={(text) => setusertoken(text)} 104 autocapitalize={'none'} 105 keyboardtype={'default'} 106 /> 107 \<touchableopacity onpress={() => verifyotp()}> 108 \<view style={styles button}> 109 \<text style={styles button label}>{'verify'}\</text> 110 \</view> 111 \</touchableopacity> 112 \<touchableopacity onpress={() => requestotp()}> 113 \<view style={styles button}> 114 \<text style={styles button label}>{'resend token'}\</text> 115 \</view> 116 \</touchableopacity> 117 \</view> 118 )} 119 \</view> 120 ); 121 };1 import react, {fc, reactelement, usestate} from 'react'; 2 import {alert, text, textinput, touchableopacity, view} from 'react native'; 3 import parse from 'parse/react native'; 4 import {usenavigation} from '@react navigation/native'; 5 import styles from ' /styles'; 6	 7 export const userotp fc<{}> = ({}) reactelement => { 8 const navigation = usenavigation(); 9	 10 const \[userdata, setuserdata] = usestate(''); 11 const \[usertoken, setusertoken] = usestate(''); 12 const \[tokenrequested, settokenrequested] = usestate(false); 13	 14 const requestotp = async function () promise\<boolean> { 15 // note that this values come from state variables that we've declared before 16 const userdatavalue string = userdata; 17 // check if value is an email if it contains @ note that in a real 18 // app you need a much better validator for this field 19 const verificationtype string = 20 userdatavalue includes('@') === true ? 'email' 'sms'; 21 // we need to call it using await 22 try { 23 await parse cloud run('requestotp', { 24 userdata userdatavalue, 25 verificationtype verificationtype, 26 }); 27 // show token input field 28 settokenrequested(true); 29 alert alert('success!', `token requested via ${verificationtype}!`); 30 return true; 31 } catch (error) { 32 alert alert('error!', error message); 33 return false; 34 } 35 }; 36	 37 const verifyotp = async function () promise\<boolean> { 38 // note that this values come from state variables that we've declared before 39 const userdatavalue string = userdata; 40 const usertokenvalue string = usertoken; 41 // check if value is an email if it contains @ note that in a real 42 // app you need a much better validator for this field 43 const verificationtype string = 44 userdatavalue includes('@') === true ? 'email' 'sms'; 45 // we need the installation id to allow cloud code to create 46 // a new session and login user without password; this is obtained 47 // using a static method from parse 48 const parseinstallationid string = await parse getinstallationid(); 49 // we need to call it using await 50 try { 51 // verify otp, if successful, returns a sessionid 52 let response object = await parse cloud run('verifyotp', { 53 userdata userdatavalue, 54 verificationtype verificationtype, 55 usertoken usertokenvalue, 56 parseinstallationid parseinstallationid, 57 }); 58 if (response sessionid !== undefined) { 59 // use generated sessionid to become a user, 60 // logging in without needing to inform password and username 61 await parse user become(response sessionid); 62 const loggedinuser parse user = await parse user currentasync(); 63 alert alert( 64 'success!', 65 `user ${loggedinuser get('username')} has successfully signed in!`, 66 ); 67 // navigation navigate takes the user to the home screen 68 navigation navigate('home'); 69 return true; 70 } else { 71 throw response; 72 } 73 } catch (error) { 74 alert alert('error!', error message); 75 return false; 76 } 77 }; 78	 79 return ( 80 \<view style={styles login wrapper}> 81 {tokenrequested === false ? ( 82 \<view style={styles form}> 83 \<textinput 84 style={styles form input} 85 value={userdata} 86 placeholder={'email or mobile phone number'} 87 onchangetext={(text) => setuserdata(text)} 88 autocapitalize={'none'} 89 keyboardtype={'email address'} 90 /> 91 \<touchableopacity onpress={() => requestotp()}> 92 \<view style={styles button}> 93 \<text style={styles button label}>{'request otp'}\</text> 94 \</view> 95 \</touchableopacity> 96 \</view> 97 ) ( 98 \<view style={styles form}> 99 \<text>{'inform the received token to proceed'}\</text> 100 \<textinput 101 style={styles form input} 102 value={usertoken} 103 placeholder={'token (6 digits)'} 104 onchangetext={(text) => setusertoken(text)} 105 autocapitalize={'none'} 106 keyboardtype={'default'} 107 /> 108 \<touchableopacity onpress={() => verifyotp()}> 109 \<view style={styles button}> 110 \<text style={styles button label}>{'verify'}\</text> 111 \</view> 112 \</touchableopacity> 113 \<touchableopacity onpress={() => requestotp()}> 114 \<view style={styles button}> 115 \<text style={styles button label}>{'resend token'}\</text> 116 \</view> 117 \</touchableopacity> 118 \</view> 119 )} 120 \</view> 121 ); 122 }; dai un'occhiata più da vicino alle requestotp requestotp e verifyotp verifyotp funzioni, che sono responsabili della chiamata alle rispettive funzioni cloud code e della validazione della loro risposta maggiori dettagli su come funzionano possono essere ispezionati nei commenti del codice dopo aver creato il nuovo schermo, importalo e dichiaralo nel tuo app js app js (o app tsx app tsx ) dopo di che, aggiungi un nuovo pulsante nel tuo userlogin js userlogin js (o userlogin tsx userlogin tsx ) file, consentendo al tuo utente di navigare verso lo schermo otp 4 testare la nuova funzionalità otp testiamo ora le nostre modifiche all'app prima di tutto, registra un nuovo utente contenente un'email valida e un numero di telefono assicurati di utilizzare il formato di notazione internazionale (e 164) nel numero di telefono (ad es +14155552671) ora, naviga alla schermata otp dalla schermata di accesso e informa la stessa email o numero di telefono di prima clicca sul pulsante di richiesta e dovresti ricevere un messaggio come questo, cambiando l'input attivo sullo schermo se hai fornito un indirizzo email, dovresti ricevere un'email contenente il token otp; se è stato fornito un numero di telefono, riceverai un messaggio sms sul tuo cellulare l'email dovrebbe contenere un messaggio come questo, a seconda di come hai impostato il modello sendgrid inserisci il token otp e clicca su verifica se tutto è andato bene, ora dovresti essere nella schermata principale con il seguente messaggio conclusione alla fine di questa guida, hai imparato come utilizzare le funzioni del codice cloud di parse per integrare servizi di terze parti nella tua applicazione react native nella prossima guida, imparerai come lavorare con gli utenti in parse