# Sign in with Email/Phone

> **Concepts:** Learn about how [**Sign in with Email/Phone Number**](https://docs.cotter.app/features/verify-email-phone) works.

### Overview

Verifying **email and phone number** in your mobile app using our React Native SDK consists of the following steps:

1. Call Cotter's Login function
2. Setup deep linking
3. Receive user's email or phone number, and whether or not it's verified

### What you're building

![Cotter's React Native SDK on Android and iOS](https://107069962-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M0QGDMRD8y_Kd-BpOvT%2F-M1dkT-G7fDVGrUF2H8j%2F-M1dlHYUGE23fmcVeogG%2Fimage.png?alt=media\&token=34a05903-fa2c-4d3d-a828-4614ee3890c2)

## Steps

1. [Import Cotter as a dependency](https://docs.cotter.app/sdk-reference/react-native-sdk-verify-email-phone#step-1-import-cotter-as-a-dependency)
2. [Call Cotter's Verify function](https://docs.cotter.app/sdk-reference/react-native-sdk-verify-email-phone#step-2-call-cotters-verify-function): This function will handle the WebView, verifying phone number or email, and request the identity from Cotter's server.
3. [Setup deep linking](https://docs.cotter.app/sdk-reference/react-native-sdk-verify-email-phone#step-3-setup-deep-linking): Cotter's authentication will redirect back to your application using a URL scheme.
4. [Receive the Token](https://docs.cotter.app/sdk-reference/react-native-sdk-verify-email-phone#step-4-receiving-the-token-in-onsuccess-or-onerror): Include the returned token and email/phone number in your server

### Step 1: Import Cotter as a dependency

{% hint style="info" %}
Make sure you're using `react-native` version **< 0.63**
{% endhint %}

{% tabs %}
{% tab title="yarn" %}

```java
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
```

{% endtab %}

{% tab title="npm" %}

```
npm install --save 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
```

{% endtab %}
{% endtabs %}

*(Optional) Checkout additional steps* [*for Android, React Native < 0.60, and Manual Installation*](https://docs.cotter.app/sdk-reference/react-native/installation)*.*&#x20;

### 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

1. Open the web browser with **no predefined input**. The user can enter email or phone in the in-app browser.

```javascript
// 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

```javascript
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);
  };
  ...
}
```

{% hint style="success" %}
**Try this now!** You should see an in-app browser looking like the image below popping up and ask you to authenticate.
{% endhint %}

![](https://107069962-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M0QGDMRD8y_Kd-BpOvT%2F-M1doINBc43yOQlb662u%2F-M1doM-5Nwjmc8sO7YxE%2Fimage.png?alt=media\&token=35555bd7-178f-4ae7-932b-0e80d1716970)

**Send Code via WhatsApp**

Instead of using SMS, you can also [send the verification code via WhatsApp.](https://docs.cotter.app/sdk-reference/react-native/older-sdk-versions/sending-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](https://github.com/cotterapp/react-native-sdk/blob/9bc206e3b5c815a5ded65627e8bb172db293f83d/examples/android/app/src/main/AndroidManifest.xml#L23)

```markup
<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](https://github.com/cotterapp/react-native-cotter/blob/master/examples/ios/examples/Info.plist#L26)

```markup
<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](https://github.com/proyecto26/react-native-inappbrowser/blob/master/example/ios/example/AppDelegate.m):

{% tabs %}
{% tab title="iOS 9.x or newer" %}

```swift
// 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];
}
```

{% endtab %}
{% endtabs %}

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](https://github.com/proyecto26/react-native-inappbrowser/blob/master/example/ios/example/AppDelegate.m):

```swift
// 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](https://github.com/proyecto26/react-native-inappbrowser/blob/master/example/ios/example/AppDelegate.m):

```swift
// 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

{% tabs %}
{% tab title="React Navigation" %}
In your App.js

```javascript
import { createStackNavigator } from 'react-navigation'

// Import Cotter's Loading Page
import { LoadingPage } from 'react-native-cotter';
 
const Main = createStackNavigator(
  {
    ...
    Register: { screen: Register },
    
    // Redirect users Cotter's Handler page
    CotterLoadingVerify: { 
      screen: LoadingPage, // Use Cotter's Loading Page
      path: 'auth_callback' // Enable Deep linking redirection
    },
    
  }
)
```

If you have Nested Stack Navigator, add `path: ''` to every parent stack.

```javascript
// TARGET STACK
const RegisterStack = createStackNavigator(
  {
    Register: { screen: Register },
    CotterLoadingVerify: {
      screen: LoadingPage, // Use Cotter's Loading Page
      path: 'auth_callback', // Enable Deep linking redirection
    },
  }
);

// PARENT 1
const RootStack = createStackNavigator(
  {
    // ADD path: '' here
    RegisterStack: { screen: RegisterStack, path: '' },
    ...
  }
);

// PARENT of PARENT 1
const RootSwitch = createSwitchNavigator(
  {
    Splash: { screen: Splash },
    // ADD path: '' here
    RootStack: { screen: RootStack, path: '' },
  }
);
```

{% endtab %}

{% tab title="React Navigation 5 or above" %}
If you're using the [newer version of React Navigation](https://reactnavigation.org/docs/deep-linking#deep-link-integration), copy paste the code below to your App.js or index.js.

**In your App.js or index.js**

```javascript
import { NavigationContainer, useLinking } from '@react-navigation/native';

function App() {
  const ref = React.useRef();

  const {getInitialState} = useLinking(ref, {
    prefixes: ['https://myexample.cotter.app', 'myexample://'],
    config: {
      CotterLoadingVerify: 'auth_callback', // ADD THIS TO REDIRECT TO COTTER'S HANDLER PAGE
    },
  });

  const [isReady, setIsReady] = React.useState(false);
  const [initialState, setInitialState] = React.useState();

  React.useEffect(() => {
    Promise.race([
      getInitialState(),
      new Promise(resolve =>
        // Timeout in 150ms if `getInitialState` doesn't resolve
        // Workaround for https://github.com/facebook/react-native/issues/25675
        setTimeout(resolve, 150)
      ),
    ])
      .catch(e => {
        console.error(e);
      })
      .then(state => {
        if (state !== undefined) {
          setInitialState(state);
        }

        setIsReady(true);
      });
  }, [getInitialState]);

  if (!isReady) {
    return null;
  }

  return (
    <NavigationContainer initialState={initialState} ref={ref}>
      {/* content 👈 */}
    </NavigationContainer>
  );
}
```

**In your Router**

```javascript
import {LoadingPage} from 'react-native-cotter';

function Router() {
  return (
    <Stack.Navigator>
      ...
      
      // Add CotterLoadingVerify page
      <Stack.Screen
        name="CotterLoadingVerify"
        component={LoadingPage}
        options={{headerShown: false}}
      />
      
    </Stack.Navigator>
  );
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Remember to make sure your [callbackURL in Step 2 ](https://docs.cotter.app/sdk-reference/react-native-sdk-verify-email-phone#step-2-call-cotters-verify-function)is correct.
{% endhint %}

{% hint style="success" %}
**Try it again!** You should see the in-app browser redirecting back after you've successfully verified.
{% endhint %}

### 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:

```javascript
{
  "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` .&#x20;

* 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 the `receiver` field, and a signature to ensure this is from Cotter. The token tells you that this `identifier` is verified.

{% hint style="success" %}
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](https://docs.cotter.app/sdk-reference/react-native-sdk-verify-email-phone#step-5-validating-the-token) is valid.
{% endhint %}

For example, if you have an existing Register function:

```javascript
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&#x20;

Checkout how to verify the OAuth Tokens from Cotter here:

{% content-ref url="../../../getting-access-token/verifying-jwt-tokens" %}
[verifying-jwt-tokens](https://docs.cotter.app/getting-access-token/verifying-jwt-tokens)
{% endcontent-ref %}

## 🎉 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:

* [Only allow your website/app to use your API Key](https://docs.cotter.app/protecting-your-account/only-allow-your-website-app-to-use-your-api-key)
* [Rate Limit the number of authentication requests](https://docs.cotter.app/protecting-your-account/rate-limit)
* [Enable reCAPTCHA to prevent automated abuse](https://docs.cotter.app/protecting-your-account/enable-recaptcha-to-protect-against-automated-abuse)
