> ## Documentation Index
> Fetch the complete documentation index at: https://docs.streambird.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrate SMS OTP with Existing Auth flow

You can use MoonKey Auth to complement your existing authentication as a 2-factor authentication method.

This example assumes that you are using the MoonKey Auth API in your backend using your MoonKey `ApiKey` that has access to your entire `App` on MoonKey.

## 1 - Implement OTP UI

Implement 2 UI screens to enable OTP

1. Screen to enter phone number

<Frame>
  <img width="50%" src="https://mintcdn.com/streambird-23/PiBN7-K0u0e27Xai/images/otp-phone-number-ui.png?fit=max&auto=format&n=PiBN7-K0u0e27Xai&q=85&s=d93cf0415545ae25d65d0896a310b8fe" data-path="images/otp-phone-number-ui.png" />
</Frame>

2. Screen to submit OTP

<Frame>
  <img width="50%" src="https://mintcdn.com/streambird-23/PiBN7-K0u0e27Xai/images/otp-confirm-ui.png?fit=max&auto=format&n=PiBN7-K0u0e27Xai&q=85&s=2cc23b56830eb1d1ed59fcd1f00bd2e5" data-path="images/otp-confirm-ui.png" />
</Frame>

## 2 - Create or Update an existing user

Each user must be stored on MoonKey Auth, so we recommend ensuring that you store our auto generated User ID from the response into your database/backend in a column or field against that user (as long as you can associate your user with the auto generated ID returned by MoonKey).

We will ensure that each mobile number or email is ONLY attached to a single user at any time. If this is an existing user, we will be using the [**CreateUser**](/api-reference/users/create-user) endpoint to create a user, otherwise, you should use the [**UpdateUser**](/api-reference/users/update-user) endpoint to attach the phone number to the user by sending in the user's MoonKey user ID.

### Create user

```bash cURL theme={null}
curl --location --request POST 'https://api.moonkey.fun/v1/auth/users/create' \
--header 'Authorization: Bearer sk_test_KJuRUZmh1XC342h1n39gH84MuSZDyD13NfhtDkaY6IfwpQA0H' \
--header 'Content-Type: application/json' \
--data-raw '{
    "phone_number": "+14152222222"
}'
```

### Update user

```bash cURL theme={null}
curl --location --request POST 'https://api.moonkey.fun/v1/auth/users/user_24wFP9pDa9YiMJLun94iKykoZs2/update' \
--header 'Authorization: Bearer sk_test_KJuRUZmh1XC342h1n39gH84MuSZDyD13NfhtDkaY6IfwpQA0H' \
--header 'Content-Type: application/json' \
--data-raw '{
    "phone_numbers": [
        "phone_number": "+14152222222"
    ]
}'
```

## 3 - Send OTP by SMS

Once we have a user associated with the phone number. We can initiate a SMS OTP request to the phone number using [**CreateSmsOTP**](/api-reference/otps/create-sms-otp) endpoint.

```bash cURL theme={null}
curl --location --request POST 'https://api.moonkey.fun/v1/auth/otps/sms/send' \
--header 'Authorization: Bearer sk_test_KJuRUZmh1XC342h1n39gH84MuSZDyD13NfhtDkaY6IfwpQA0H' \
--header 'Content-Type: application/json' \
--data-raw '{
    "phone_number": "+14152222222"
}'
```

## 4 - Verify OTP (One-time passcode)

In the previous step, MoonKey Auth will return a response like the following,

```json JSON theme={null}
{
    "phone_number_id": "pn_24oXBLRv6BoHXbNZoTAZkAFlRsy",
    "user_active": true,
    "user_id": "user_24wFP9pDa9YiMJLun94iKykoZs2"
}
```

The `phone_number_id` will be used as the `method_id` in the [**VerifyOTP**](/api-reference/otps/verify-otp-one-time-passcode) endpoint.

```bash cURL theme={null}
curl --location --request POST 'https://api.moonkey.fun/v1/auth/otps/verify' \
--header 'Authorization: Bearer sk_test_KJuRUZmh1XC342h1n39gH84MuSZDyD13NfhtDkaY6IfwpQA0H' \
--header 'Content-Type: application/json' \
--data-raw '{
    "method_id": "pn_24oXBLRv6BoHXbNZoTAZkAFlRsy",
    "otp": "982303"
}'
```

If you send in `session_token` or `session_expires_in` parameters, a new session will then be created or extended for the given user and the session token returned.

```json JSON theme={null}
{
    "method_id": "pn_24oXBLRv6BoHXbNZoTAZkAFlRsy",
    "method_type": "phone_number",
    "session_token": "Fe8byh3HfbdopzNBu36hSMBDYDZGJAegwE9PvA3R0Ynqw1GBMpnABxuOveA0sAhU",
    "user_id": "user_24wFP9pDa9YiMJLun94iKykoZs2"
}
```

You can then return your existing access token or session cookie to your user like you currently do in your application.

In the case where the user typed in invalid OTP, we will return

```json JSON theme={null}
{
    "status_code": 400,
    "error_message": "Invalid OTP Code.",
    "error_type": "invalid_otp"
}
```

You can return or display this error to your user via your API or application.

Voila! You have now integrated 2-factor Authentication (2FA/MFA) and Signup into your application without building and maintaining additional infrastructures. Let us take care of Authentication and you can focus on your core product.

<Tip>
  This `session_token` returned can also be used and stored with the user browser-side via cookie/localStorage if you want to use our Sessions API provided by MoonKey to manage sessions lifecyle for your User.
</Tip>
