# Sign in with Email/Phone

> **Concepts:** Learn about how [**Sign in with Email/Phone Number**](/features/verify-email-phone.md) 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](/files/-M1dlHYUGE23fmcVeogG)

## Steps

1. [Import Cotter as a dependency](/sdk-reference/react-native/react-native-sdk-verify-email-phone.md#step-1-import-cotter-as-a-dependency)
2. [Call Cotter's Verify function](/sdk-reference/react-native/react-native-sdk-verify-email-phone.md#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](/sdk-reference/react-native/react-native-sdk-verify-email-phone.md#step-3-setup-deep-linking): Cotter's authentication will redirect back to your application using a URL scheme.
4. [Receive the Token](/sdk-reference/react-native/react-native-sdk-verify-email-phone.md#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*](/sdk-reference/react-native/installation.md)*.*&#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 %}

![](/files/-M1doM-5Nwjmc8sO7YxE)

**Send Code via WhatsApp**

Instead of using SMS, you can also [send the verification code via WhatsApp.](/sdk-reference/react-native/older-sdk-versions/sending-code-via-whatsapp.md)

### 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 ](/sdk-reference/react-native/react-native-sdk-verify-email-phone.md#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](/sdk-reference/react-native/react-native-sdk-verify-email-phone.md#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="/pages/-M4HZPVawEx2QN3qLmnv" %}
[Verifying JWT Tokens](/getting-access-token/verifying-jwt-tokens.md)
{% 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](/protecting-your-account/only-allow-your-website-app-to-use-your-api-key.md)
* [Rate Limit the number of authentication requests](/protecting-your-account/rate-limit.md)
* [Enable reCAPTCHA to prevent automated abuse](/protecting-your-account/enable-recaptcha-to-protect-against-automated-abuse.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.cotter.app/sdk-reference/react-native/older-sdk-versions/sign-in-with-email-phone.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
