# Add Email/Phone Verification

Most of the time, it's required for you to check if the user's identifier (their email or phone number) is valid. With Cotter, you can verify your users via email, SMS, or WhatsApp.&#x20;

## Step 1: Set Up Deep Linking

The verification will follow OAuth's PKCE flow which will open an in-app browser where your user can enter the OTP sent to their email/phone.

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 iOS**

Add the following to your `ios/Runner/Info.plist`.

{% code title="ios/Runner/Info.plist" %}

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

{% endcode %}

**Setup in Android**

Add the following to your `android/app/src/main/AndroidManifest.xml`.

{% code title="android/app/src/main/AndroidManifest.xml" %}

```markup
<manifest ...>
    <application ...> 
    ...

    <!-- Add the lines from here -->
    <activity android:name=".CallbackActivity" >
      <intent-filter android:label="flutter_web_auth">
        <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 -->
        <data android:scheme="myexample" android:host="auth_callback"/>
      </intent-filter>
    </activity>
    <!-- Until here -->

  </application>
</manifest>
```

{% endcode %}

> You may need to stop `flutter-run` and re-run it to see the changes.

## Step 2: Update your Sign Up Function

Make sure you followed the guide for [Sign In with Device](https://docs.cotter.app/sdk-reference/flutter/sign-in-with-device). Update your [Sign Up Function that you made on Step 2](https://docs.cotter.app/sdk-reference/flutter/sign-in-with-device#step-2-make-a-sign-up-function).

There are 2 ways to do this:

* [**Verify the email/phone number first**](#option-1-verifying-before-registering-the-user), then continue registering the user if verification is successful
* [**Finish registering the user first**](#option-2-verifying-after-registering-the-user), then allow the user to verify their email/phone number later.

### Option 1: Verifying Before Registering the User

This will work the following way:

1. The user will be asked to verify their email or phone number
2. If verification successful, we'll create a new User
3. Then, set up the current device as trusted.

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

```dart
// 2️⃣  Make Sign Up Function
  void signUp(BuildContext context) async {
    try {
      // ❌ Remove this line
      var user = await cotter.signUpWithDevice(identifier: inputController.text);
      
      // ✅ Add the lines from here
      // (1) Verify the user's email
      // (2) Create the user if verification successful
      var user = await cotter.signUpWithEmailOTP(
        redirectURL: "myexample://auth_callback",
        email: inputController.text,
      );
      // (3) Set up the current device as trusted
      user = await user.registerDevice();
      // To here
       
    } catch (e) {
      print(e);
    }
  }
```

{% endtab %}

{% tab title="Phone (with Pre-built UI)" %}

```dart
// 2️⃣  Make Sign Up Function
void signUp(BuildContext context) async {
  try {
    // ❌ Remove this line
    var user = await cotter.signUpWithDevice(identifier: inputController.text);
    
    // ✅ Add the lines from here
    // (1) Verify the user's phone
    // (2) Create the user if verification successful
    var user = await cotter.signUpWithPhoneOTP(
      redirectURL: "myexample://auth_callback",
      channels: [PhoneChannel.SMS, PhoneChannel.WHATSAPP], // optional, default is SMS
    );
    // (3) Set up the current device as trusted
    user = await user.registerDevice();
    // To here
     
  } catch (e) {
    print(e);
  }
}
```

{% endtab %}

{% tab title="SMS" %}

```dart
// 2️⃣  Make Sign Up Function
void signUp(BuildContext context) async {
  try {
    // ❌ Remove this line
    var user = await cotter.signUpWithDevice(identifier: inputController.text);
    
    // ✅ Add the lines from here
    // (1) Verify the user's phone
    // (2) Create the user if verification successful
    var user = await cotter.signInWithPhoneOTPViaSMS(
                  redirectURL: "myexample://auth_callback",
                  phone: inputController.text,
                );
    // (3) Set up the current device as trusted
    user = await user.registerDevice();
    // To here
     
  } catch (e) {
    print(e);
  }
}
```

{% endtab %}

{% tab title="WhatsApp" %}

```dart
// 2️⃣  Make Sign Up Function
void signUp(BuildContext context) async {
  try {
    // ❌ Remove this line
    var user = await cotter.signUpWithDevice(identifier: inputController.text);
    
    // ✅ Add the lines from here
    // (1) Verify the user's phone
    // (2) Create the user if verification successful
    var user = await cotter.signInWithPhoneOTPViaWhatsApp(
                  redirectURL: "myexample://auth_callback",
                  phone: inputController.text,
                );
    // (3) Set up the current device as trusted
    user = await user.registerDevice();
    // To here
     
  } catch (e) {
    print(e);
  }
}
```

{% endtab %}
{% endtabs %}

### Option 2: Verifying After Registering the User

This will work the following way:

1. The user will enter some identifier (email or phone number), and we'll create a new User with that unverified identifier.
2. Set up the current device as trusted.
3. Once the user is logged-in, ask the user to verify their email/phone number

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

```dart
// 2️⃣  Make Sign Up Function
void signUp(BuildContext context) async {
  try {
    var user = await cotter.signUpWithDevice(identifier: inputController.text);
    
    // ✅ Add the line below
    // (3) Verify the user's email 
    user = await user.verifyEmailWithOTP(redirectURL: "myexample://auth_callback");
     
  } catch (e) {
    print(e);
  }
}
```

{% endtab %}

{% tab title="SMS" %}

```dart
// 2️⃣  Make Sign Up Function
void signUp(BuildContext context) async {
  try {
    var user = await cotter.signUpWithDevice(identifier: inputController.text);
    
    // ✅ Add the line below
    // (3) Verify the user's phone 
    user = await user.verifyPhoneWithOTPViaSMS(redirectURL: "myexample://auth_callback");

  } catch (e) {
    print(e);
  }
}
```

{% endtab %}

{% tab title="WhatsApp" %}

```dart
// 2️⃣  Make Sign Up Function
void signUp(BuildContext context) async {
  try {
    var user = await cotter.signUpWithDevice(identifier: inputController.text);
    
    // ✅ Add the line below
    // (3) Verify the user's phone 
    user = await user.verifyPhoneWithOTPViaWhatsApp(redirectURL: "myexample://auth_callback");

  } catch (e) {
    print(e);
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Make sure that the `identifier` that you used inside `cotter.signUpWithDevice` has the correct type. (If the identifier is an email, then use `verifyEmailWithOTP`, and so on).
{% endhint %}

## 🎉 You're done! <a href="#youre-done" id="youre-done"></a>

You should now be able to enter your email or phone number during the signup process.
