# Sign In with Email/Phone Number

> **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](#step-1-import-cotter-as-a-dependency)
2. [Sign Up or Login with Email or Phone](#step-2-signing-up-or-logging-in)
3. [Setup deep linking](#step-3-setup-deep-linking): Cotter's authentication will redirect back to your application using a URL scheme.
4. [Receive the Token](#step-4-receiving-the-token-in-onsuccess-or-onerror): Include the returned OAuth 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: Signing Up or Logging In

#### Sign Up: Use the sign up method to:

* Verify the user's email or phone number
* Then create a new user in Cotter if successful
* **If you passed-in the email/phone into the function**: if your user already exists, **it will return an error "User already exists"**
* **If you does not pass in the email/phone into the function:** users can enter their email/phone in the pop-up browser, but it will NOT check if the user already exists. It will behave like the Log In method below.

> **Tip:** Use the "Sign Up" method and pass in the user's email/phone to differentiate new and existing user. You can have an input text and collect the user's email/phone.

#### Log In: Use the login method to:

* To authenticate a user based on their email.
* If the user doesn't exist, this method **will automatically create a new user.**

> **Tip:** Use the "Log In" method to login or register user on the same page

{% tabs %}
{% tab title="Using Email" %}

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

let cotter = new Cotter(API_KEY_ID);   // your API_KEY_ID
await cotter.signUpWithEmailLink(      // use Email & Magic Link
  'myexample://auth_callback',         // (setup later) URL Scheme for deep linking
  (resp) => {console.log(resp)},       // Success Callback Function
  (err) => {console.log(err)}, // Error Callback Function
  {email: this.state.email},           // (Optional) , if you leave this blank, user can enter email in the in-app browser
);
```

#### Sign Up

* **Magic Link:** use `cotter.signUpWithEmailLink`
* **OTP:** use `cotter.signUpWithEmailOTP`

#### Sign In

* **Magic Link:** use `cotter.signInWithEmailLink`
* **OTP:** use `cotter.signInWithEmailOTP`

**If no email is specified**, the user can enter the email in the in-app browser
{% endtab %}

{% tab title="Using Phone" %}

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

let cotter = new Cotter(API_KEY_ID);            // your API_KEY_ID
await cotter.signUpWithPhoneLink(               // use Phone & Magic Link
  'myexample://auth_callback',                  // (setup later) URL Scheme for deep linking
  (resp) => {console.log(resp)},                // Success Callback Function
  (err) => {console.log(err)},          // Error Callback Function
  {phone: this.state.phone, channel: "SMS" },   // (Optional), if you leave this blank, user can enter email in the in-app browser
);
```

#### **Sign Up**

* **Magic Link:** use `cotter.signUpWithPhoneLink`
* **OTP:** use `cotter.signUpWithPhoneOTP`

#### **Sign In**

* **Magic Link:** use `cotter.signInWithPhoneLink`
* **OTP:** use `cotter.signInWithPhoneOTP`

#### Channels: (default to "SMS" if phone is specified)

* To use SMS: `{phone: this.state.phone, channel: "SMS"}`
* To use WhatsApp: `{phone: this.state.phone, channel: "WHATSAPP"}`

**If no phone number is specified**, the user can enter the phone number in the in-app browser and there will be buttons for WhatsApp and SMS available (based on your settings in the Dashboard > Branding).

{% hint style="info" %}
To send code/link via SMS or WhatsApp, you'll need to add some balance to you project in the [Dashboard](https://dev.cotter.app/).
{% endhint %}
{% endtab %}
{% endtabs %}

{% 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)

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

{% hint style="warning" %}
Make sure your URL scheme (the front part before `://`) doesn't have an underscore or other special characters. To test it out, enter your Redirect URL here: <https://jsfiddle.net/omd02jn5/>
{% endhint %}

### Setup in Android

Add this in your [android/app/src/main/**AndroidManifest.xml**](https://github.com/cotterapp/react-native-cotter/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 [ios/\<YourAppName>/Info.plist](https://github.com/cotterapp/react-native-cotter/blob/master/examples/ios/examples/Info.plist#L26)

```markup
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>

	<!-- ADD THE LINES FROM HERE -->
	<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>
	<!-- TO HERE -->

	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
```

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 ](#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": "f4286df9-a923-429c-bc33-5089ffed5f68",
    "created_at": "2020-07-21T22:53:21.211367Z",
    "updated_at": "2020-07-21T22:53:21.211367Z",
    "deleted_at": "0001-01-01T00:00:00Z",
    "identifier": "putri@cotter.app", // User's email
    "identifier_type": "EMAIL",
    "device_type": "BROWSER",
    "device_name": "Mozilla/5.0 (Linux; Android 9; Android SDK built for x86 Build/PSR1.180720.075) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36",
    "expiry": "2020-08-20T22:53:21.19705Z",
    "timestamp": "2020-07-21T22:53:21.19705Z"
  },
  "oauth_token": {
    "access_token": "eyJhbGciOiJFUz...", // Validate this access token
    "id_token": "eyJhbGciOiJFUzI1...",
    "refresh_token": "27944:lb31DY5pG229n...",
    "expires_in": 3600,
    "token_type": "Bearer",
    "auth_method": "OTP"
  },
  "token": {...},
  "user": {
    "ID": "643a42c7-316a-4abe-b27e-f4d0f903bfea", // [Deprecated] Cotter uesr ID
    "identifier": "putri@cotter.app",
    ...
  }
}
```

{% hint style="warning" %}
Please use the identifier (email/phone number) as your main way to identify users, **user.ID is deprecated.**
{% endhint %}

This JSON object contains 3 objects, `identifier` , `oauth_token` and `user` .&#x20;

* The identifier object contains information about the user's email or phone number, device type and name, and expiry.
* The `oauth_token` contains an `access_token` that you can validate in your backend.
* The `user` contains the User object in Cotter, which includes a "Cotter User ID". **You should associate your user with this Cotter User ID for reference.**

{% 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 access token is valid.](https://docs.cotter.app/getting-access-token/verifying-jwt-tokens)
{% endhint %}

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