Sign In with Device

Cotter's iOS SDK offers the easiest way to integrate "Sign in with device" to your ios app. You can simply call a function and it does most of the heavy lifting and authentication for you.

Concepts: Learn about how Sign in with Device works.

There are major updates planned for this feature. Contact us in Slack so we can help you prepare for it.

Overview

Authenticating users using Trusted Devices with Cotter's iOS SDK consists of the following steps:

  1. Import and Initialize Cotter

  2. Calling functions to register devices a Trusted Device

  3. Calling functions to authenticate from Trusted and Non-Trusted Device

What you're building

Steps

  1. Set Allowed Methods in the Dashboard to allow Trusted Devices

  2. Create a User: Create a user in Cotter by specifying your user ID.

Step 1. Import Cotter as a dependency

We use Cocoapods as our SDK host. If you're using Cocoapods, add this to your Podfile

pod 'Cotter'

Then simply run pod install

Step 2. Set allowed Authentication Methods in the Developer Dashboard

You need to set allowed methods for authenticating your users. To allow TRUSTED DEVICES, go to https://dev.cotter.app/rules

Remember to select the correct project in the dropdown list.

Step 3. Creating a User

Registering a new User

Passwordless.shared.registerWith(identifier: input){ (user: CotterUser?, err:Error?) in
    if err != nil {
        // handle error here
    }
    
    if user != nil {
        // you can save cotter's user id in your database here
    }
}

Check out Create a User API Reference for a full description

Step 4. Initialize Cotter

You can now use the SDK to enroll and verify Trusted Devices for the user you just created.

In your main view controller, initialize Cotter with API keys, Cotter's URL to use (prod/test), and your User ID.

Production Endpoint: https://www.cotter.app/api/v0

let cotter = Cotter(
  apiSecretKey: <your-api-secret-key>,
  apiKeyID: <your-api-key-id>,
  cotterURL: "https://www.cotter.app/api/v0",
  userID: <your-user-id>, // user's id that will be registered/created later
  configuration: [:]
)

Example:

class SomeUIVC: UIViewController {
  var cotter: Cotter?

  override func viewDidLoad() {
    super.viewDidLoad()

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

Step 5. Register this device as a Registered Trusted Device

Right after your user finished their registration to your app, you should automatically register the device as a Trusted Device (or prompt your user if they want to make this device as a Trusted Device).

To enroll the current device as a TrustedDevice, call the CotterAPIService.shared.enrollTrustedDevice function, which takes in a userID as String and a Callback function as parameters.

Example:

func enrollTrustedDeviceForUser(userID: String) {
  CotterAPIService.shared.enrollTrustedDevice(userID: userID, cb: { response in
      switch response {
      case .success(let user):
        print("Successfully enrolled existing user \(user.id): \(user.enrolled)")
      case .failure(let err):
        // you can put exhaustive error handling here
        print(err.localizedDescription)
      }
  })
}

enrollTrustedDeviceForUser(userID: "hello@example.com")

JSON Result:

{
  "ID": "746500ae-a5cd-4692-8fd0-49d57cf7cc57", // User ID from Cotter's system
  "created_at": "2020-02-25T04:08:26.174597Z",
  "update_at": "2020-02-27T22:20:31.333154814Z",
  "deleted_at": null,
  "issuer": "afcabd98-745f-4b9e-98de-af968d9951d3", // your API KEY ID
  "client_user_id": "1014", // you client's user ID
  "enrolled": [ // Enrolled Authentication Methods
    "PIN",
    "BIOMETRIC",
    "TRUSTED_DEVICE" // This should be added to enrolled methods once enrollDevice successful
  ],
  "default_method": "TRUSTED_DEVICE" // This will automatically be the last enrolled method, which is Trusted Device in this case
}

This method is only for the first Trusted Device. You will get an error if you attempt to enroll another Trusted Device using enrollDevice when there's already a Trusted Device for the account. To enroll other devices, see Add a new Trusted Device.

Step 6. Authenticate from a Trusted Device

To authenticate a device, call the cotter?.loginWithTrustedDevice function, which takes in the current view controller and a Callback function as parameters. This will automatically detect whether the current device is a Trusted Device or not.

Example:

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:

{
  "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 below about Non-Trusted Device
  "approved": true, // Is this event approved.
  "signature": "oonMGCAxp3..." // Signature to make sure this event comes from Cotter's server
}

An Event is an Authentication Event, where your app requests Cotter's SDK to authenticate the user. EVENT_NAME refers to what type of authentication event was requested. Example: LOGIN event, TRANSACTION event, UPDATE_PROFILE event, etc.

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

Case 1: The current device is a Trusted Device

If the current device is a Trusted Device, it should automatically be approved, and you will receive a JSON result containing the requested Event and whether or not it's approved. The approval is based on whether or not the signature included in the request from the SDK is valid.

{
  ...
  "method": "TRUSTED_DEVICE",
  "new": false, // Is this a new pending event (should be false).
  "approved": true // Is this event approved (should be true).
}

You should see a result that the event is not new, and that it's approved. This is because the signature from the Trusted Device is sufficient to prove that the device is authorized.

The callback that you provided to the cotter?.loginWithTrustedDevice function will be called on login success or failure. For instance, as seen in the above example, if the login is approved, the callback function will be called with no error, and you can redirect the user to the Dashboard View Controller. However, if the login is not approved, then an error will exist and you can redirect the user to the Error Page View Controller.

When passing this Event Response to your backend, you need to check if this JSON is valid and if it comes from Cotter's server.

Checkout how to verify the OAuth Tokens from Cotter here:

pageVerifying JWT Tokens

Case 2: The current device is not a Trusted Device

We'll cover this in the next guide:

pageAdd a New Trusted Device

Last updated