Before we begin, let's discuss why you want to secure your applications with the IDlayr SubscriberCheck API.
The IDlayr SubscriberCheck API
The IDlayr SubscriberCheck API confirms the ownership of a mobile phone number by verifying the possession of an active SIM card with the same number. It also exposes a flag that indicates if the SIM card associated with the mobile phone number has changed within the last seven days. This check provides the security required for passwordless login with the addition of attempted fraud detection.
All your user needs to do is provide a phone number, and the API will verify that number is associated with their device. It can be used as a primary user verification mechanism or as an added layer of security against SIM swapping/theft within existing 2FA workflows. In this tutorial, we'll use SubscriberCheck as a standalone authentication mechanism.
The SubscriberCheck workflow is as follows:
- Get the user's phone number on the mobile device
- Send the phone number to the application server
- Create a SubscriberCheck using the SubscriberCheck API
- Return the SubscriberCheck URL to the mobile device
- Request the SubscriberCheck URL on the mobile device over mobile data
- Mobile device requests the SubscriberCheck result via the application server
- Application server completes the phone check a PATCH request to IDlayr's API
- Application server returns the SubscriberCheck result, including SIM changed status, to the mobile device
In this tutorial, we'll use a ready-made server and focus on the steps involving the React Native application.
Before you begin
Before you begin, there are a few requirements that have to be met:
- An Android or Apple device with a SIM card and mobile data connection
- For iOS: XCode >12
- For Android:
- JDK 14 (Java version 14.02 / Gradle v6.3).
- Android Studio or Android SDK manager via Android developer downloads. VS Code would work as you aren't using a virtual device.
- Set up the React Native Environment
- For metro bundler, Node.js version > 10
Getting Started
A IDlayr Account is needed to make the SubscriberCheck API requests, so make sure you've created one.You're also going to need some Project credentials from IDlayr to make API calls. So sign up for a IDlayr account, which comes with some free credit. We've built a CLI for you to manage your IDlayr account, projects, and credentials within your Terminal. To install the IDlayr CLI run the following command:npm install -g @tru_id/cli
tru login <YOUR_IDENTITY_PROVIDER>
(this is one of google
, github
, or microsoft
) using the Identity Provider you used when signing up. This command will open a new browser window and ask you to confirm your login. A successful login will show something similar to the below:Success. Tokens were written to /Users/user/.config/@tru_id/cli/config.json. You can now close the browser
config.json
file contains some information you won't need to modify. This config file includes your Workspace Data Residency (EU, IN, US), your Workspace ID, and token information such as your scope.Create a new IDlayr project within the root directory with the following command:tru projects:create rn-auth --project-dir .
rn-auth
directory and run the following command to clone the dev-server
:git clone [email protected]:tru-ID/dev-server.git
dev-server
directory, run the following command to create a.env
copy of .env.example
:cp .env.example .env
.env
file, update the values of TRU_ID_CLIENT_ID
andTRU_ID_CLIENT_SECRET
with your client_id
and client_secret
in yourtru.json
file.dev-server
to the Internet for your mobile application to access your backend server. For this tutorial, we're using ngrok, which we've included in the dev-server
functionality. So to start with, uncomment the following and populate them with your ngrok credentials:NGROK_ENABLED=true#NGROK_SUBDOMAIN=a-subdomain # Uncommenting this is optional. It is only available if you have a paid ngrok account.NGROK_AUTHTOKEN=<YOUR_NGROK_AUTHTOKEN> # This is found in the ngrok dashboard: https://dashboard.ngrok.com/get-started/your-authtokenNGROK_REGION=eu # This is where your ngrok URL will be hosted. If you're using IDlayr's `eu` data residency; leave it as is. Otherwise, you could specify `in` or `us`.
dev-server
directory, run the following two commands:npm install # Installs all third-party dependencies in package.jsonnpm run dev # Starts the server
To follow along with this tutorial, head over to the Passwordless Authentication with React Native repo and clone the starter-files branch via:
git clone -b starter-files https://github.com/tru-ID/passwordless-auth-react-native.git
To install dependencies, open a new terminal, cd passwordless-auth-react-native
, and run:
npm install
Once you've finished that step, start the Metro server:
npm start
Then, to run on Android, ensure your Android device is connected via USB and run:
npm run android
To run on your iOS device, ensure it's connected via USB, open ios/simcardauthrn.xcworkspace
in XCode, and run the project.
Your app should look like this:
Get the User's Phone Number on the Mobile Device
Let's start by adding the UI and state management required for the user to input (TextInput
) and submit their phone number (TouchableOpacity
). We'll also add a UI and state to check if any work is in progress via a loading
variable or an error has occurred via error
.
const App = () => {const [phoneNumber, setPhoneNumber] = React.useState('')const [loading, setLoading] = React.useState(false)const [error, setError] = React.useState(null)React.useEffect(() => {if (error) {showMessage({message: error,type: 'danger',style: styles.toastContainer,})}}, [error])// we'll handle SubscriberCheck in the function belowconst onPressHandler = () => {}return (<><StatusBar barStyle="light-content" /><SafeAreaView style={styles.container}><Image style={styles.logo} source={require('./images/tru-logo.png')} /><Text style={styles.heading}>Enter your phone number</Text><Text style={styles.paragraph}>and we'll handle the rest</Text><View style={styles.center}><TextInputstyle={styles.textInput}keyboardType="phone-pad"placeholder="ex. (415) 555-0100"placeholderTextColor="#d3d3d3"onChangeText={(text) => setPhoneNumber(text)}value={phoneNumber}/>{loading ? (<ActivityIndicatorstyle={styles.spinner}size="large"color="#00ff00"/>) : (<TouchableOpacity onPress={onPressHandler} style={styles.button}><Text style={styles.buttonText}>Authenticate</Text></TouchableOpacity>)}</View></SafeAreaView><FlashMessage /></>)}
Your app should now look like this:
The user will begin the SubscriberCheck Authentication by clicking the TouchableOpacity
(button). So, we need to set the loading state and create the payload to submit to the server. We do this within the onPressHandler
function:
const onPressHandler = async () => {setLoading(true)const body = {phone_number: phoneNumber,}console.log(body)}
Set the loading state to true
to give the user a visual cue that works (an HTTP network request) is in progress via our loading indicator. Next, we construct the body object setting the phone_number
field to the phoneNumber
.
Create a SubscriberCheck using the SubscriberCheck API
With our body request payload ready, we're ready to make requests to our server. First, let's import and setup Axios in our development server is:
import FlashMessage, { showMessage } from 'react-native-flash-message'import axios from 'axios'axios.defaults.baseURL = 'https://{subdomain}.{region}.ngrok.io'
Remember to replace https://{subdomain}.{region}.ngrok.io
with your development server URL.
Then update the onPressHandler
to make a request to create a SubscriberCheck:
const onPressHandler = async () => {setLoading(true)const body = {phone_number: phoneNumber,}console.log(body)try {const response = await axios.post('/v0.2/subscriber-check', body)console.log(response.data)} catch (e) {setLoading(false)setError(e.message)}}
Here, we make a network request to our app server's SubscriberCheck endpoint to get back the SubscriberCheck URL (check_url
) and the check_id
, which we'll use in a future step.
Request the SubscriberCheck URL on the Mobile Device over Mobile Data
The next step is requesting the SubscriberCheck URL on the mobile device over mobile data. For this, we'll use the tru.ID (IDlayr) React Native SDK.
The first step is to install it via:
npm install @tru_id/tru-sdk-react-native
Note: After installing the SDK, you should restart your Metro server, re-run npm run android
, and clean the XCode build to ensure the changes are picked up.
Then add the import
to the top of App.js
:
import TruSdkReactNative from '@tru_id/tru-sdk-react-native'
The tru.ID (IDlayr) React Native SDK openWithDataCellular(checkUrl)
function forces the request to the SubscriberCheck URL (check_url
) to go over the mobile data connection.
Add the openWithDataCellular
call to the onPressHandler
:
const onPressHandler = async () => {setLoading(true)const body = {phone_number: phoneNumber,}console.log(body)try {const response = await axios.post('/v0.2/subscriber-check', body)console.log(response.data)const checkResponse = await TruSdkReactNative.openWithDataCellular(response.data.check_url);console.log('check_url request compeleted')} catch (e) {setLoading(false)setError(e.message)}}
Complete the SubscriberCheck and get the result via the Application Server
With the check_url
request complete, you now need to take the check_url
and code
received in the final redirect of the check_url
, and pass that to the application server. The application server will then make a PATCH
request to IDlayr's API in order to complete the SubscriberCheck, and return the response back to the mobile application.
Add a new stateful value called data
:
const App = () => {const [phoneNumber, setPhoneNumber] = React.useState('')const [loading, setLoading] = React.useState(false)const [error, setError] = React.useState(null)const [data, setData] = React.useState(null)React.useEffect(() => {...
Make a request to the /v0.2/subscriber-check/exchange-code
endpoint to get the result, save it to state with setData
, and set loading to false
above the line } catch (e) {
:
if ('error' in checkResponse) {console.log(`Error in openWithDataCellular: ${checkResponse.error_description}`)setLoading(false)showMessage({message: 'Verification failed',type: 'danger',style: styles.toastContainer,})} else if ('http_status' in checkResponse) {const httpStatus = checkResponse.http_statusif (httpStatus === 200 && checkResponse.response_body !== undefined) {console.log(`Requesting PhoneCheck URL`)if ('error' in checkResponse.response_body) {const body = checkResponse.response_bodyconsole.log(`Error: ${body.error_description}`)showMessage({message: `Verification failed: ${body.error_description}`,type: 'danger',style: styles.toastContainer,})} else {const body = checkResponse.response_bodytry {const checkStatusRes = await axios.post('/v0.2/subscriber-check/exchange-code', { check_id: body.check_id, code: body.code })console.log('[CHECK RESULT]:', checkStatusRes.data)setData(checkStatusRes.data)setLoading(false)} catch (error) {showMessage({message: `Error retrieving check result: ${error.message}`,type: 'danger',style: styles.toastContainer,})return;}}} else {const body = resp.response_body;showMessage({message: `Error: ${body.detail}`,type: 'danger',style: styles.toastContainer,})}}
With that in place, your app will look as follows when creating the SubscriberCheck, requesting the check_url
using the tru.ID (IDlayr) SDK, and then retrieving the SubscriberCheck result:
Updating the UI with the result
The last thing we need to do is inform users whether or not there is a SubscriberCheck match (i.e., the phone number is verified) and if the SIM has changed recently. For this, we'll use toast notifications.
In your App()
, at the top add the following useEffect
:.
//check if there is a match, i.e., the phone number has been verified and no_sim_change and render toast UIReact.useEffect(() => {if (data) {data.match && data.no_sim_change? showMessage({message: 'Phone Verified',type: 'success',style: styles.toastContainer,}): showMessage({message: 'Verification failed',type: 'danger',style: styles.toastContainer,})}}, [data])
In this React.useEffect
function we add data
as a dependency, so whenever data
changes the effect re-runs. Inside the effect, we check if we have data and subsequently check if we have a match and if the SIM has not changed. If both are confirmed, we render a toast UI with a Phone Verified
message (this can be anything you want). Otherwise, we render a toast UI with a Verification failed. Please Try Again Later
message.
Your UI, if the SubscriberCheck is successful, should look like this:
Wrapping Up
There you have it: you’ve successfully integrated IDlayr SubscriberCheck with your React Native application to build a passwordless signup or login flow. The application verifies a phone number and determines if the SIM card for the device has changed recently.
Resources
Get in touch
If you have any questions, contact [email protected].