> For the complete documentation index, see [llms.txt](https://docs.cotter.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cotter.app/sdk-reference/ios/ios-sdk-passwordless-login/authenticate-from-a-non-trusted-device.md).

# Authenticate from a Non-Trusted Device

## **Steps**

There are 2 steps in authenticating a Non-Trusted Device

1. [Make a request](/sdk-reference/ios/ios-sdk-passwordless-login/authenticate-from-a-non-trusted-device.md#step-1-making-an-authentication-request) from the Non-Trusted Device and wait for approval
2. [Approve the request](/sdk-reference/ios/ios-sdk-passwordless-login/authenticate-from-a-non-trusted-device.md#step-2-how-to-approve-a-pending-request-from-a-trusted-device) from a Trusted Device.&#x20;

### **Step 1: Making an Authentication Request**

Same as how it works with [Authenticating from a Trusted Device](/sdk-reference/ios/ios-sdk-passwordless-login.md#step-6-authenticate-from-a-trusted-device), to authenticate a device, call the `cotter?.loginWithTrustedDevice` function. **This will automatically detect whether the current device is a Trusted Device or not.**

Example:

```swift
class SomeUIVC: UIViewController {
  var cotter: Cotter?

  override func viewDidLoad() {
    super.viewDidLoad()

    self.cotter = Cotter(
      apiSecretKey: "588d6f67-0981-4718-899b-bcd512de1aca",
      apiKeyID: "w4FK6Zz0XIhtGY3o5biI",
      cotterURL: "https://www.cotter.app/api/v0",
      userID: "hello@example.com",
      configuration: [:]
    );
  }

  // On Button Click
  @IBAction func login(_ sender: UIButton) {
    func callback(token: String, err: Error?) {
      if err != nil {
        // Failed login. Go to Error Page View Controller
        print(err?.localizedDescription)
        self.performSegue(withIdentifier: "segueToErrorView", sender: self)
        return
      }
      // Successful login. Go to Dashboard View Controller
      self.performSegue(withIdentifier: "segueToDashboard", sender: self)
    }

    /* Login using Cotter's Trusted Device Feature. */
    self.cotter?.loginWithTrustedDevice(vc: self, cb: callback)
  }
}
```

JSON Result:

```swift
{
  "ID": 1361, // Event ID
  "CreatedAt": "2020-02-27T22:22:48.705212512Z",
  "UpdatedAt": "2020-02-27T22:22:48.705212512Z",
  "DeletedAt": null,
  "client_user_id": "1014", // your client's User ID
  "issuer": "afcabd98-745f-4b9e-98de-af968d9951d3", // your API Key
  "event": "<EVENT NAME>",// requested event (LOGIN, or TRANSACTION, etc)
  "ip": "192.168.232.2", 
  "location": "Unknown",
  "timestamp": "1582842167",
  "method": "TRUSTED_DEVICE", // auth method: TRUSTED_DEVICE (other choices are PIN / BIOMETRIC)
  "new": false, // Is this a new pending event. More explanation in the next section about Non-Trusted Device
  "approved": true, // Is this event approved.
  "signature": "oonMGCAxp3..." // Signature to make sure this event comes from Cotter's server
}
```

**Event Name**

The `event` refers to what type of authentication event was requested. Example: `LOGIN` event, `TRANSACTION` event, `UPDATE_PROFILE` event, etc.

**Callback Class**

The callback should be filled with the View Controller to go to when the request is approved. For example, if this is a login request, and the request is approved, then the callback can perform a segue to your Dashboard View Controller. Else, if the login completely failed (`.failure`), then the callback can perform a segue to your 'Login Failed' View Controller.

When an Authentication Event is requested `TRUSTED_DEVICE`, there are 2 possible cases:

#### **Case 1: The current device is a Trusted Device**

You will be automatically approved if the request is coming from a Trusted Device. This is covered in [Authenticate from a Trusted Device](/sdk-reference/ios/ios-sdk-passwordless-login.md#step-6-authenticate-from-a-trusted-device).

#### **Case 2: The current device is NOT a Trusted Device**

If the current device is **not** a Trusted Device, then it will create a **pending event**. This pending event will need to be **approved by a Trusted Device**. You should see a JSON result looking like:

```swift
{
  ...
  "method": "TRUSTED_DEVICE",
  // This is a pending event. 
  // It will turn to false once there's a Trusted Device 
  // responded to approve or reject this event
  "new": true, 

  // Since it's a pending event, it's not yet approved.
  "approved": false
}
```

The SDK will automatically show a prompt for the user to approve the event from a Trusted Device.

### **Step 2: How to approve a pending request from a Trusted Device**

> Note: This is the flow for the user's trusted device to approve the login from the non-trusted device.

To check if there's a pending event for this user, you can call the `cotter?.getEventTrustedDevice` method from a Trusted Device. You can also [setup a Push Notification to be sent to the Trusted Device](/sdk-reference/ios/ios-sdk-passwordless-login/ios-push-notification.md) when there's a new Login Request.

Example:

```swift
class SomeUIVC: UIViewController {
  var cotter: Cotter?

  override func viewDidLoad() {
    super.viewDidLoad()

    self.cotter = Cotter(
      apiSecretKey: "588d6f67-0981-4718-899b-bcd512de1aca",
      apiKeyID: "w4FK6Zz0XIhtGY3o5biI",
      cotterURL: "https://www.cotter.app/api/v0",
      userID: "hello@example.com",
      configuration: [:]
    )
  }

  // On Button Click
  @IBAction func checkForPendingEvent(_ sender: UIButton) {

    /* Checks for pending event associated with the userID. If an event exists, 
        a prompt in the trusted device would pop up. If not, nothing happens. 
        As such, you don't need to pass in a callback function in this case. */
    self.cotter?.getEventTrustedDevice(vc: self, cb: nil)
  }
}
```

> In the future, your app that is installed in a Trusted Device will receive a notification and this method is invoked when the notification is opened.

For now, you should tell your user to press a button and invoke this method when they try to login from a non-trusted device.

The SDK will open a prompt in the Trusted Device asking if the user want to approve or reject the authentication request

![Prompt to approve request from a Trusted Device](/files/-M4uoEprkSyImPXQGf6w)

### **Receiving the result and check if the request was approved**

> Note: This is the flow for the user's non-trusted device that requested the login.

#### **Case 1: The request is approved**

When the request is approved, the SDK will automatically redirect to your Callback function, which will be in the form of [`FinalAuthCallback`](/sdk-reference/ios/older-versions/ios-sdk.md#the-callbacks).

#### Handle the response in your callback class

If the login is approved, then an `Error` does not exist, and you can redirect the user to, for instance, the Dashboard View Controller (Successful login).

Example:

```swift
func callback(token: String, err: Error?) {
  if err != nil {
    // Failed login. Go to Error Page View Controller
    print(err?.localizedDescription)
    self.performSegue(withIdentifier: "segueToErrorView", sender: self)
    return
  }
  // Successful login. Go to Dashboard View Controller
  self.performSegue(withIdentifier: "segueToDashboard", sender: self)
}
```

#### **Case 2: The request is rejected**

However, if the request is not approved for 1 minute, the prompt in the Non-Trusted Device will show an error message (will auto-dismiss in 3 seconds). The prompt will not show an error immediately when the Trusted Device denied the request, i.e. there is no difference between rejection and no response from the Trusted Device.

![Authentication request from a Non-Trusted Device](/files/-M4uoTKTWEXuqEXE0n1g)

In this case, after the prompt is dismissed, the user will remain on the same view where he/she started the prompted the authentication request.
