Sign in with Email/Phone
Our React Native SDK offers the easiest way to integrate Cotter 's email/phone verification. You can simply call a function and it does most of the heavy lifting and authentication for you.
Concepts: Learn about how Sign in with Email/Phone Number works.
Overview
Verifying email and phone number in your mobile app using our React Native SDK consists of the following steps:
Call Cotter's Login function
Setup deep linking
Receive user's email or phone number, and whether or not it's verified
What you're building

Steps
Call Cotter's Verify function: This function will handle the WebView, verifying phone number or email, and request the identity from Cotter's server.
Setup deep linking: Cotter's authentication will redirect back to your application using a URL scheme.
Receive the Token: Include the returned token and email/phone number in your server
Step 1: Import Cotter as a dependency
yarn add react-native-cotter react-native-device-info rn-secure-storage react-native-randombytes react-native-camera react-native-svg react-native-securerandom buffer react-native-inappbrowser-reborn react-native-sha256
npx pod-install ios
(Optional) Checkout additional steps for Android, React Native < 0.60, and Manual Installation.
Step 2: Call Cotter's Verify function
Cotter's verify function will open a Custom Chrome Tab or ASWebAuthenticationSession in your app to authenticate the user. You have 2 choices
Open the web browser with no predefined input. The user can enter email or phone in the in-app browser.
// ADD Cotter's Verify Class
import { Verify } from 'react-native-cotter';
class Register extends PureComponent {
...
openCotterAuth = async () => {
var verify = new Verify(
'myexample://auth_callback', // (setup later) URL Scheme for deep linking
API_KEY_ID, // your API_KEY_ID
this.onError, // error callback Function, receives (errorMessage, errorObject)
this.onSuccess, // error callback Function, receives (errorMessage, errorObject)
);
await verify.openAuth('EMAIL'); // EMAIL or PHONE
// You will need balance to send SMS. Otherwise, use "EMAIL"
};
onError = (errorMessage, errorObject) => {
alert(errorMessage);
console.log(errorObject);
};
onSuccess = response => {
alert("Success");
console.log(response);
};
...
}
2. Open the web browser after the user entered their email or phone number in your app's input field
import { Verify } from 'react-native-cotter';
class Register extends PureComponent {
...
openCotterAuth = async () => {
var verify = new Verify(
'myexample://auth_callback', // (setup later) URL Scheme for deep linking
API_KEY_ID, // your API_KEY_ID
this.onError, // error callback Function, receives (errorMessage, errorObject)
this.onSuccess, // error callback Function, receives (errorMessage, errorObject)
);
await verify.openAuthWithInput('EMAIL', this.state.email); // EMAIL or PHONE
};
onError = (errorMessage, errorObject) => {
alert(errorMessage);
console.log(errorObject);
};
onSuccess = response => {
alert("Success");
console.log(response);
};
...
}
Try this now! You should see an in-app browser looking like the image below popping up and ask you to authenticate.

Send Code via WhatsApp
Instead of using SMS, you can also send the verification code via WhatsApp.
Step 3: Setup Deep Linking
Pick a unique URL scheme for redirecting the user back to your app after the verification in the in-app browser is successful. For this example, we'll use myexample://auth_callback
.
Setup in Android
Add this in your AndroidManifest.xml
<activity
android:name=".MainActivity"
android:launchMode="singleTask"> <!-- Make launchMode to singleTask -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- Setup Deep Linking Here -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- This is for myexample://auth_callback -->
<!-- 👇 Change this to your own URL scheme -->
<data android:scheme="myexample" android:host="auth_callback"/>
</intent-filter>
<!-- end -->
</activity>
Setup in iOS
Add this in your Info.plist
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>myexample</string> <!-- 👈 Change this to your own URL Scheme -->
<key>CFBundleURLSchemes</key>
<array>
<string>myexample</string> <!-- 👈 Change this to your own URL Scheme -->
</array>
</dict>
</array>
If you're targeting iOS 9.x or newer, add the following lines to YourApp/ios/YourApp/AppDelegate.m:
// Add the header at the top of the file:
#import <React/RCTLinkingManager.h>
// Add this above `@end`:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [RCTLinkingManager application:application openURL:url options:options];
}
If you're targeting iOS 8.x or older, you can use the following code instead, add the following lines to YourApp/ios/YourApp/AppDelegate.m:
// Add the header at the top of the file:
#import <React/RCTLinkingManager.h>
// Add this above `@end`:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [RCTLinkingManager application:application openURL:url
sourceApplication:sourceApplication annotation:annotation];
}
If your app is using Universal Links, you'll need to add the following code as well, add the following lines to YourApp/ios/YourApp/AppDelegate.m:
// Add this above `@end`:
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity
restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
return [RCTLinkingManager application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
Setup in React Native Project
Try it again! You should see the in-app browser redirecting back after you've successfully verified.
Step 4: Receiving the Token in onSuccess or onError
onError
The onError
function that you pass in will receive 2 parameters: errorMessage
(string) and errorResponse
(object). The errorResponse
is an http response from attempt to verify the user's email/phone in Cotter's server.
onSuccess
The onSuccess
function that you pass in will receive a response
object that looks like this:
{
"identifier": {
"ID": "3e61e1e9-3528-48d7-a7a2-b985141f4d67",
"created_at": "2020-02-15T03:45:25.656423Z",
"update_at": "2020-02-19T06:55:19.121863Z",
"deleted_at": null,
"identifier": "+12345678910",
"identifier_type": "PHONE",
"public_key": "hU1ZOLxyfq548Vh45TcOlqHug/WHqVJfoxApgq8Wfks=",
"device_type": "BROWSER",
"device_name": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36",
"expiry": "2020-03-20T06:55:19.121783Z"
},
"token": {
"identifier": "+12345678910",
"identifier_type": "PHONE",
"receiver": "<your API_KEY_ID>",
"expire_at": "1584687591",
"signature": "G8dOKR6qLj+GiB0pD2aggVVdYddFoyy..."
}
}
This JSON object contains 2 objects, identifier
and token
.
The identifier object contains information about the user's email or phone number, device type and name, and expiry.
The token contains the user's phone number, your
API_KEY_ID
in thereceiver
field, and a signature to ensure this is from Cotter. The token tells you that thisidentifier
is verified.
You should include this JSON Object into your call to your backend for Login or Registration. Your backend should then verify that the signature of the token is valid.
For example, if you have an existing Register function:
class Register extends PureComponent {
...
// YOUR BUTTON SHOULD INVOKE openCotterAuth ON PRESS
openCotterAuth = async () => {
var verify = new Verify(
'myexample://auth_callback', // (setup later) URL Scheme for deep linking
API_KEY_ID, // your API_KEY_ID
this.onError, // error callback Function, receives (errorMessage, errorObject)
this.onSuccess, // error callback Function, receives (errorMessage, errorObject)
);
await verify.openAuthWithInput("EMAIL", this.state.email); // EMAIL or PHONE
// You will need balance to send SMS. Otherwise, use "EMAIL"
};
onError = (errorMessage, errorObject) => {
alert(errorMessage);
console.log(errorObject);
};
onSuccess = response => {
this.submitRegister(response.identifier.identifier, response.token);
};
// YOUR Register API post email and token
submitRegister = (email, token) => {
axios
.post(
"https://example.com/user/register",
{ email: email, token: token }, // SEND Cotter's token to your backend
false
)
.then(response => {
...
this.props.navigation.navigate("Dashboard");
})
.catch(error => {});
};
...
}
Validating Cotter's Access Token
Checkout how to verify the OAuth Tokens from Cotter here:
Verifying JWT Tokens🎉 You're done!
Securing your Project
Since you'll be using your API Key from a front-end website or mobile app, your API_KEY_ID
is exposed to anyone inspecting your code. Here are some ways to prevent abuse:
Last updated