Skip to content

twilio/twilio-verify-sna-ios

Repository files navigation

Twilio Verify SNA

Swift Package Manager Compatible Platform Swift 5.5 License

Table of Contents

About


Twilio Silent Network Auth will protect you against account takeovers (ATOs) that target your user's phone number by streamlining your methods for verifying mobile number possession. Instead of sending one-time passcodes (OTPs) that can be stolen or forcing users to implement complicated app-based solutions, Twilio Silent Network Auth will verify mobile number possession directly on the device by using its built-in connectivity to the mobile operators’ wireless network.

This SDK will help you with processing the SNA URL's provided by our Verify services to silently validate a phone number.

See Technical Overview

See Silent Network Auth Overview

Dependencies


External dependencies:

  • None

Internal dependencies:

  • SNANetworking: used for cellular networking operations, lives as an internal package.

Requirements


  • iOS 12+
  • Swift 5.5
  • Xcode 14.x

Documentation


Offical documentation will be added via Twilio docs once this project gets released.

Installation


During the current phase of this project, we only support SPM. We have plans to support CocoaPods and Carthage once we release this product.

Swift Package Manager

For pilot stage: you will need to create a personal access token on your Github account in order to add this dependency via Xcode (assuming that you have 2FA enabled) since this project is private.

Package.swift

dependencies: [
    .package(
        url: "https://github.com/twilio/twilio-verify-sna-ios.git",
        .upToNextMajor(from: "0.0.7")
    )
]

Usage


For using the SDK you can follow the next steps:

  1. Import the SDK dependency, on your .swift file:
import TwilioVerifySNA
  1. Instantiate the SDK
private lazy var twilioVerify: TwilioVerifySNA = TwilioVerifySNABuilder.build()
  1. Process the SNA URL by calling the method:
func processURL(
  _ url: String,
  onComplete: @escaping ProcessURLCallback
)
twilioVerify.processURL(snaUrlFromBackend) { result in
    switch result {
      case .success:
      // Handle success scenario

      case .failure(let error):
      // Handle error scenario
    }
}

Async alternative:

func processURL(_ url: String) async -> ProcessURLResult
let result = await twilioVerify.processURL(snaUrlFromBackend)

switch result {
  case .success:
  // Handle success scenario

  case .failure(let error):
  // Handle error scenario
}
  1. Full implementation demonstration
import UIKit
import TwilioVerifySNA

class ViewController: UIViewController {
  private lazy var twilioVerify: TwilioVerifySNA = TwilioVerifySNABuilder.build()

     override func viewDidLoad() {
        super.viewDidLoad()
    }

    private func validateSNAURL() async {
        let snaUrlFromBackend = await asyncMethodToGetSNAUrl()

        twilioVerify.processURL(snaUrlFromBackend) { result in
            switch result {
                case .success:
                // Handle success scenario

                case .failure(let error):
                // Handle error scenario
            }
        }
    }
}

Running the Sample app


For running the demo you will need to create a sample backend, this backend will communicate with the Twilio Verify Services and provide to the client a SNA URL that this SDK will use to validate across the carrier cellular network.

Important note:

The demo app needs to run on a real device with a working SIM-CARD and internet connection (provided by the sim-card, not WiFi).

Currently it's not possible to test the functionality using a simulator.

To run the sample app:

  1. Clone the repo
  2. Open the TwilioVerifySNA.xcworkspace file
  3. Select the TwilioVerifySNADemo project
  4. Go to Signing & Capabilities
  5. Change the Bundle Identifier to something unique, now you have two options: A. Create provisioning profiles on your Apple Developer account using the bundle identifier you just assigned B. Check the Automatically manage signing checkbox with your Apple Developer account logged in.
  6. Connect or prepare your test device
  7. Run the TwilioVerifySNADemo schema on your test device

Running the Sample backend


To be added once the sample backend gets released.

Using the sample app

To validate a phone number:

  • Set the phone number
    • Available carriers during this phase:
      • US - Verizon, TMO
      • UK - EE, Vodafone, O2 and ThreeUK
      • CA - Bell, Rogers and Telus
  • Set the country code (only US during pilot stage)
  • Set your sample backend url
  • Submit the form by using the CTA button

Expected behavior: The app will ask the network carrier if the provided phone number is the same used on the network request, if the phone number is correct, then the app will redirect to a success screen.

Errors


Celullar network

See NetworkResult.h

Name Description Technical cause
CannotObtainNetworkInterfaces Cannot obtain network interfaces of the local system Probably you are using a simulator or a device with no sim-card
CannotFindRemoteAddressOfRemoteUrl Cannot find remote address of requested URL The url is corrupted, try generating a new one
CannotFindRoutesForHttpRequest No routes found for HTTP request The url is corrupted, try generating a new one
UnableToInstantiateSockets Cannot instantiate socket Probably you are using a simulator or a device with no sim-card
ErrorReadingHttpResponse Error occurred while reading HTTP response No bytes received from the request
CannotSpecifySSLFunctionsNeeded Cannot specify SSL functions needed to perform the network I/O operations The url is corrupted, try generating a new one
CannotSpecifySSLIOConnection Error occurred while specifying SSL I/O connection with peer Probably you are using a simulator or a device with no sim-card
PeersCertificateDoesNotMatchWithRequestedUrl The common name of the peer's certificate doesn't match with URL being requested Unknown network error, try again
ErrorPerformingSSLHandshake Error occurred while performing SSL handshake The device probably lost internet connection during the operation
ErrorPerformingSSLWriteOperation Error occurred while performing SSL write operation The url is corrupted, try generating a new one
SSLSessionDidNotCloseGracefullyAfterPerformingSSLReadOperation Cannot specify SSL functions needed to perform the network I/O operations The url is corrupted, try generating a new one
UnknownHttpResponse Unknown HTTP response

Networking

See NetworkRequestProvider+Errors.swift

Name Description Technical cause
RequestFinishedWithNoResult No response from request The request was successful (200 status code) but the networking layer was unable to get the response
CellularRequestError Error processing the URL via cellular network The cause will be represented by a Cellular network error

Request manager errors

See RequestManager+Errors.swift

Name Description Technical cause
InvalidUrl Invalid url, please check the format. Unable to convert the url string to an Apple URL struct
NoResultFromUrl Unable to get a valid result from the requested URL. Unable to get a redirection path or a result path from the url, probably the SNAURL is corrupted (or maybe expired)
InstanceNotFound Unable to continue url process, instance not found. Weak self was nil, make sure that you are instantiating as a dependency this SDK or lazy loading it, do not use this SDK as a computed property.
NetworkingError Check network error cause

Verification errors

See TwilioVerifySNA+Errors.swift

Name Description Technical cause
CellularNetworkNotAvailable Cellular network not available Cellular network not available, check if the device has cellular internet connection or you are not using a simulator or iPad
RequestError Error processing the SNAURL request, see the RequestError cause for detail

Getting the error cause

You can get the cause for an error accessing the associated error

twilioVerify.processURL(snaUrl) { result in
    switch result {
        case .success:
          return

        case .failure(let error):
            switch error {
                case .cellularNetworkNotAvailable:
                    return

                case .requestError(.instanceNotFound):
                    return

                case .requestError(.invalidUrl):
                    return

                case .requestError(.noResultFromUrl):
                    return

                case .requestError(.networkingError(.requestFinishedWithNoResult)):
                    return

                case .requestError(.networkingError(.cellularRequestError(.cannotConnectSocketToRemoteAddress))):
                    return

                case .requestError(.networkingError(.cellularRequestError(.success))):
                    return

                case .requestError(.networkingError(.cellularRequestError(.unexpectedError))):
                    return

                case .requestError(.networkingError(.cellularRequestError(.unknownHttpResponse))):
                    return

                case .requestError(.networkingError(.cellularRequestError(.errorReadingHttpResponse))):
                    return

                case .requestError(.networkingError(.cellularRequestError(.unableToInstantiateSockets))):
                    return

                case .requestError(.networkingError(.cellularRequestError(.errorPerformingSSLHandshake))):
                    return

                case .requestError(.networkingError(.cellularRequestError(.cannotSpecifySSLIOConnection))):
                    return

                case .requestError(.networkingError(.cellularRequestError(.cannotObtainNetworkInterfaces))):
                    return

                case .requestError(.networkingError(.cellularRequestError(.cannotFindRoutesForHttpRequest))):
                    return

                case .requestError(.networkingError(.cellularRequestError(.cannotSpecifySSLFunctionsNeeded))):
                    return

                case .requestError(.networkingError(.cellularRequestError(.errorPerformingSSLWriteOperation))):
                    return

                case .requestError(.networkingError(.cellularRequestError(.cannotFindRemoteAddressOfRemoteUrl))):
                    return

                case .requestError(.networkingError(.cellularRequestError(.peersCertificateDoesNotMatchWithRequestedUrl))):
                    return

                case .requestError(.networkingError(.cellularRequestError(.sslSessionDidNotCloseGracefullyAfterPerformingSSLReadOperation))):
                    return
            }
    }
}

Error description and technical discussion:

twilioVerify.processURL(snaUrl) { result in
    switch result {
        case .success:
          return

        case .failure(let error):
          let errorDescription = cause.description
          let technicalError = cause.technicalError
    }
}

Privacy Manifest

This document serves as the Privacy Manifest for the Twilio Verify SNA SDK. It outlines the privacy practices implemented in this SDK, providing a comprehensive understanding of how we handle data and respect user privacy.

Purpose

The primary purpose of this Privacy Manifest is to facilitate developers and organizations in providing Apple with detailed information about the privacy practices employed within this SDK.

Usage

To use this Privacy Manifest, simply refer to the relevant sections when you need to provide information to Apple or any other interested parties about the privacy practices used in this SDK.

Contributing


This project welcomes contributions. Please check out our Contributing guide to learn more on how to get started.

License

Apache © Twilio Inc.

About

Twilio Verify SNA SDK provides the verification of mobile number possession directly on the device by using its built-in connectivity to the mobile operators’ wireless network.

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published