# 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 <a href="#overview" id="overview"></a>

Verifying **email and phone number** in your mobile app using our Flutter 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 <a href="#what-youre-building" id="what-youre-building"></a>

![Sign in with Phone Number via SMS or WhatsApp using Cotter's Flutter SDK](https://107069962-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M0QGDMRD8y_Kd-BpOvT%2F-MAUaH6nyBixniiQjNa5%2F-MAUae53veN1fusT15hG%2FFlutterPhoneLogin.gif?alt=media\&token=4375e653-c78e-483c-b988-dc4d0614f3f3)

## Steps

1. [Import Cotter as a dependency](#step-1-import-cotter-as-a-dependency)
2. &#x20;[Setup Deep Linking](#step-2-setup-deep-linking)
3. [Signing up](#step-3-signing-up)
4. [Logging in](#step-4-logging-in)
5. [Verifying a logged-in user](#step-5-verifying-a-logged-in-user)

### Step 1: Import Cotter as a dependency

Add Cotter to your `pubspec.yaml` , then run `flutter pub get`.

{% code title="pubspec.yaml" %}

```yaml
dependencies:
  cotter:
```

{% endcode %}

Check the latest releases in [pub.dev](https://pub.dev/packages/cotter#-installing-tab-). You may need to restart your flutter for it to run pod install (stop flutter run and re run it).

**For Android**: Update `minSdkVersion` to `18` [following the installation instructions](https://docs.cotter.app/sdk-reference/flutter).

### Step 2: Setup 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.&#x20;

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 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="com.linusu.flutter_web_auth.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 3: Signing Up

Make sure you have set up the deep-linking above.

{% tabs %}
{% tab title="Using Email" %}
Use the sign up method to:

* Verify the user's email
* Then create a new user in Cotter if successful

```dart
import 'package:cotter/cotter.dart'; // Import Cotter

Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
  var user = await cotter.signUpWithEmailOTP(
    redirectURL: "myexample://auth_callback",
    email: inputController.text, // Optional, if you leave this blank, user can enter email in the in-app browser
  );
  print(user);
} catch (e) {
  print(e);
}
```

{% endtab %}

{% tab title="Using Phone Number" %}
Use the sign up method to:

* Verify the user's phone number
* Then create a new user in Cotter if successful

**Option 1:** You want to use Cotter's input form inside the in-app browser. This helps with validating the input.

```dart
import 'package:cotter/cotter.dart'; // Import Cotter

Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
  var user = await cotter.signUpWithPhoneOTP(
    redirectURL: "myexample://auth_callback",
    channels: [PhoneChannel.SMS, PhoneChannel.WHATSAPP], // optional, default is SMS
  );
} catch (e) {
  print(e);
}
```

**Option 2:** You want to use your own input form and buttons. You can present 2 buttons to allow sending the OTP via WhatsApp or SMS.

* **Using SMS:**

```dart
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
  var user = await cotter.signUpWithPhoneOTPViaSMS(
              redirectURL: "myexample://auth_callback",
              phone: inputController.text,
            );
} catch (e) {
  print(e);
}
```

* **Using WhatsApp:**

```dart
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
  var user = await cotter.signUpWithPhoneOTPViaWhatsApp(
              redirectURL: "myexample://auth_callback",
              phone: inputController.text,
            );
} catch (e) {
  print(e);
}
```

{% endtab %}
{% endtabs %}

### Step 4: Logging-In

{% tabs %}
{% tab title="Using Email" %}
To authenticate an existing user by verifying their email:

> This method will create a new user if one doesn't exist.

```dart
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
  var user = await cotter.signInWithEmailOTP(
        redirectURL: "myexample://auth_callback",
        email: inputController.text, // Optional, if you leave this blank, user can enter email in the in-app browser
      );
} catch(e) {
  print(e);
}
```

{% endtab %}

{% tab title="Using Phone Number" %}
To authenticate by verifying user's phone number:

**Option 1:** You want to use Cotter's input form inside the in-app browser. This helps with validating the input.

> This method will create a new user if one doesn't exist.

```dart
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
  var user = await cotter.signInWithPhoneOTP(
    redirectURL: "myexample://auth_callback",
    channels: [PhoneChannel.SMS, PhoneChannel.WHATSAPP], // optional, default is SMS
  );
} catch (e) {
  print(e);
}
```

**Option 2:** You want to use your own input form and buttons. You can present 2 buttons to allow sending the OTP via WhatsApp or SMS.

* **Using SMS:**

```dart
try {
  var user = await cotter.signInWithPhoneOTPViaSMS(
              redirectURL: "myexample://auth_callback",
              phone: inputController.text,
            );
} catch (e) {
  print(e);
}
```

* **Using WhatsApp:**

```dart
try {
  var user = await cotter.signInWithPhoneOTPViaWhatsApp(
              redirectURL: "myexample://auth_callback",
              phone: inputController.text,
            );
} catch (e) {
  print(e);
}
```

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

### Step 5: Verifying a logged-in user

{% tabs %}
{% tab title="Using Email" %}
To verify the email of a user that is currently logged-in:

```dart
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
  var user = await cotter.getUser();
  user = await user.verifyEmailWithOTP(redirectURL: "myexample://auth_callback");
} catch (e) {
  print(e);
}
```

{% endtab %}

{% tab title="Using Phone Number" %}
To verify the phone number of a user that is currently logged-in:

* Using SMS:

```dart
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
  var user = await cotter.getUser();
  user = await user.verifyPhoneWithOTPViaSMS(redirectURL: "myexample://auth_callback");
} catch (e) {
  print(e);
}
```

* Using WhatsApp:

```dart
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
  var user = await cotter.getUser();
  user = await user.verifyPhoneWithOTPViaWhatsApp(redirectURL: "myexample://auth_callback");
} catch (e) {
  print(e);
}
```

{% endtab %}
{% endtabs %}

## 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! <a href="#youre-done" id="youre-done"></a>

### Getting the Logged-in User

Cotter's SDK automatically saves the logged-in user in your device's secure storage. Check out how to get the user information:

{% content-ref url="getting-the-logged-in-user" %}
[getting-the-logged-in-user](https://docs.cotter.app/sdk-reference/flutter/getting-the-logged-in-user)
{% endcontent-ref %}

### Getting OAuth Tokens

Cotter also automatically generates an `access_token`, `id_token` , and `refresh_token` that is securely stored in the device's secure storage. Check how to get these tokens:

{% content-ref url="getting-oauth-tokens" %}
[getting-oauth-tokens](https://docs.cotter.app/sdk-reference/flutter/getting-oauth-tokens)
{% endcontent-ref %}

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