Skip to contentSkip to navigationSkip to topbar
On this page

Verify Push and Silent Device Approval Best Practices for Production use



Purpose

purpose page anchor

Verify Push and Silent Device Approval is designed for global, web-scale use. The Twilio Verify platform that it's built on verifies over 200 million users annually. To fully realize the benefits of Verify Push in your own real-world production implementation, we've compiled a running list of best practices to consider. These best practices are organized as Q&A under these topics:

  1. Conversion Rate
  2. Security
  3. Client App
  4. Performance
  5. Project Management
  6. Testing
  7. Common Issues

1. What are methods to ensure that the device receives the challenge?

1-what-are-methods-to-ensure-that-the-device-receives-the-challenge page anchor

A critical step in the Verify Push verification sequence is for the app on the registered device and the user to be made aware that a pending challenge has been created by the customer backend/Verify Push API. We recommend starting with the "poll for the challenge" method, and then supplementing with push notifications for a better user experience. Both approaches are described below.

Poll for the Challenge

poll-for-the-challenge page anchor

Once the pending Challenge has been created in the Verify API, your mobile app needs to become aware of it. This can be done by telling your user to open up your mobile app on the registered device, and then having your app check (poll) the Verify API for any pending Challenges whenever it's opened.

Polling implementation tips

You can set up the Verify Push API (technically Notify) to send a visible push notification to your mobile app whenever a pending Challenge is created. This is a great user experience as the user can see the push notification on their device's lock screen. However, this method might fail in certain scenarios like poor connectivity, the app being in a closed state, or users turning off push notifications. This is why we recommend always implementing the previous "poll for the challenge" method as a backup.

Push notification implementation tips

  1. Configure app to receive push notifications, including background notifications that can still be received by the app even if the user has disabled visible push notifications when the app is in foreground.
  2. If the app is closed when it receives the push notification, it should attempt to store the challenge_sid and factor_sid contained in the push notification's payload, so that it can immediately poll the Verify Push API with that data when it's next opened.
  3. Give the user the option to request another push notification if they didn't get the first one. Resend for the same Challenge using the Notifications resource.
  4. Nudge the user to enable visible push notifications after they register their device, so that they will see a push notification on the lock screen of their device
  5. Have the app send a confirmation to the customer backend when it receives a push notification from Verify Push (Notify). If the customer backend doesn't receive a confirmation from the app after an expected latency from when the challenge was created, then the customer backend should assume that the push notification failed and resend.
  6. Customer backend should subscribe to debugger webhooks for the Verify Service. These webhooks contain error codes published by Verify Push, including errors related to push notification failures.

As shown in the screenshots below, TransferWise's implementation illustrates several of the best practices described earlier, such as instructing the user to "approve this login by opening the TransferWise app" and offering the option to "resend push on phone".

2020-10-07 at 11.15.27 AM.
2020-10-07 at 11.15.35 AM.

2. In which countries does it work?

2-in-which-countries-does-it-work page anchor

Unlike SMS, which has country-specific constraints due to Carriers being country-specific, Verify Push works whenever there's an internet/data connection and on any device that runs standard iOS, Android, or a supported web browser. The exceptions to this that we are aware of are:

  • Android devices built by Huawei that don't support Google Messaging Services, including Firebase Cloud Messaging, won't be able to receive push notifications. However there are workarounds to this as explained in "what are methods to ensure that the device receives the challenge?"
  • Country prohibitions defined in Twilio's general export control policy (e.g. Iran)

1. If a user installs the app on their device, registers the device, deletes the app, and then reinstalls it on the same device, will the device become registered again?

1-if-a-user-installs-the-app-on-their-device-registers-the-device-deletes-the-app-and-then-reinstalls-it-on-the-same-device-will-the-device-become-registered-again page anchor

No, deleting the app from the device completely unregisters the device from Verify Push.

2. How do I support multiple devices per user?

2-how-do-i-support-multiple-devices-per-user page anchor

From a technical perspective, a user can register multiple devices as factors. From a security policy perspective, the decision of whether to allow a user to enroll more than one device as a factor is up to you. The benefit of doing so is that it makes it more convenient for the user to respond to a push from multiple devices and it creates redundancy if they were to lose one device. The downside is that it increases the attack surface for a fraudster. Note that querying the SDK on an enrolled device will only return the factor(s) created on the same device, so a fraudster wouldn't be able to discover all of a user's registered device.

3. Can the user receive/approve a push if they aren't logged into our app

3-can-the-user-receiveapprove-a-push-if-they-arent-logged-into-our-app page anchor

You can configure Verify Push such that the user can receive/approve a push in the app on the registered device, even if they aren't logged into their account on that app. Conversely, you can require that they login first (using a different verification) before approving the push.


1. How do I know if the user uninstalls my app?

1-how-do-i-know-if-the-user-uninstalls-my-app page anchor

When the app is uninstalled, if you send a challenge to a user, your backend will receive an OK about creating the challenge, but your Twilio debugger(link takes you to an external page) will receive an error because the push notification couldn't be sent:

You can add a webhook for Twilio debugger(link takes you to an external page) and you will receive an event when this error happens. The event will be sent only one time after the app was installed. After this, push notifications will not be sent.

You can identify the factor, entity and service sid related to the error. The Payload.more_info will contain the values in the correlationIds field:

1
"more_info": {
2
"bindingType": "fcm",
3
"primaryCorrelationId": "RU1997axxxxxxxxxxxxxxxxxx5eb0cd4cd",
4
"bindingSid": "BS35bc1xxxxxxxxxxxxxxxxxxa120437c1",
5
"providerMessageId": "RU23c27xxxxxxxxxxxxxxxxxx753723240",
6
"requestId": "RQ8202exxxxxxxxxxxxxxxxxx6082c6805",
7
"correlationIds": "[VAf510xxxxxxxxxxxxxxxxxxb8ae2e7251, test-identity, YF0314fxxxxxxxxxxxxxxxxxx1349180db, YC03b4fxxxxxxxxxxxxxxxxxx13491tf45]",
8
"notificationSid": "NT033xxxxxxxxxxxxxxxxxx487ed02cd34",
9
"module": "FCMBA",
10
"description": "401 http response from Fcm Service",
11
"isPassthrough": "false",
12
"deliverySid": "DA3e727xxxxxxxxxxxxxxxxxxa3647a384",
13
"fromReference": "CRe07eaxxxxxxxxxxxxxxxxxx59d45351c"
14
}

You can get the factor sid from the correlationIds field, and delete the factor in the Verify Push backend from your backend.

Keep in mind

  • There is not a specific order of the correlationIds values. So you will not always receive them in that order.
  • The debugger events cannot be filtered by verify service sid as verify webhooks. The debugger webhooks are configured for your account, but you will receive the verify service in the correlationIds field.

iOS APNs recently stopped in November 2020 sending an error, so this debugger webhook will not work for iOS anymore. An alternative solution is to create logic in your backend that looks at whether your app has been active recently and whether previously created challenges have been verified to determine whether the app is still installed or not. If not, then delete the factor. This logic can also work for Android as an additional app uninstall detection method.

2. How do I handle different dev environments?

2-how-do-i-handle-different-dev-environments page anchor

We recommend creating different Verify Services for each environment (e.g. one for testing, one for production). Also, take into account that iOS uses different APN environments according to the signing certificate.

  • For development, you should use an 'Apple Push Notification service SSL (Sandbox)' certificate or an 'Apple Push Notification service SSL (Sandbox & Production)' certificate, and your push credential's Sandbox option should be checked.
  • For production, you should use an 'Apple Push Notification service SSL (Sandbox & Production)' certificate, and your push credential's Sandbox option should be unchecked.
  • It is better to use a different push credential for each verify service per environment

3. How do I support user language preferences?

3-how-do-i-support-user-language-preferences page anchor

Verify Push receives the message and details that could be shown to the user (depends on your implementation). We recommend using the user language preference for your app to send the message and details in the correct language. For example, if your user language in your app is French, you should send the challenge's message and details in French.

4. How do I handle users who disable push notification for my app?

4-how-do-i-handle-users-who-disable-push-notification-for-my-app page anchor

Some users may choose to disable push notifications from your app in their OS settings. This just means that the user won't see the notification in the OS's notifications drawer/center. However, APNs and FCM will still work behind-the-scenes. Pushes will still be delivered directly to your app, if it's in the foreground. Specifically:

For Android, if notifications are disabled, your user won't see a notification outside of your app, but you will still receive the push in your app if it is in foreground and the push token won't change.

For iOS, if notifications are disabled, the system delivers all remote notifications to your app silently so you will receive the push if it is in foreground in the method userNotificationCenter(_:willPresent:withCompletionHandler:)(link takes you to an external page). Getting the device token will depend on your implementation. For example, if you call registerForRemoteNotifications only if notification permission is enabled(link takes you to an external page), you won't get a device token, see sample app(link takes you to an external page).

5. How do I get the push token?

5-how-do-i-get-the-push-token page anchor

You will need the device push token to create factors.

For Android, you should get the push token(link takes you to an external page) before creating a factor and validate your app has a value for it. Getting a registration token can fail, and you will receive an exception(link takes you to an external page).

For iOS, you should get a push token before creating a factor and validate your app has a value for it. Getting a device token can fail, and you will receive a call for the method application(_:didFailToRegisterForRemoteNotificationsWithError:)(link takes you to an external page)

Take into account that the device/registration token could change, so the app should identify this case and update all the factors in the device, for reference: updated push token for Android(link takes you to an external page) and updated push token for iOS(link takes you to an external page)

6. How do I de-duplicate challenges that are approving the same action?

6-how-do-i-de-duplicate-challenges-that-are-approving-the-same-action page anchor

Your backend can generate an action_id that is unique to the verification action that needs to be approved by your user, and provide it in the HiddenDetails property of the Challenge. The HiddenDetails value of a Challenge is visible to the mobile client and can be used to de-dup Challenges with the same action_id without querying the your customer backend.

However, your mobile client will still need to query your backend to find if a given Challenge and associated action_id was approved, especially if the user has the option of simultaneously verifying the same action via another verification method, like SMS OTP.


1. What is the expected latency for API responses?

1-what-is-the-expected-latency-for-api-responses page anchor

The overall Verify API SLA for the latency of responses to requests is 300ms. This is measuring the time from when the request is received by the Verify API to when it sends the response. A different latency measure is the round-trip-time (RTT) latency, which is measured from when the request is sent by the requester to when the requester receives the response from the Verify API. RTT latency will be longer than the responses-to-requests latency, and will vary depending on the physical distance of the requester to Verify API's servers, which are located in the US East Coast by default. If you want to reduce RTT latency, try two things:

  1. Try to reduce the overall number of requests you're making to the Verify API. While this won't reduce the RTT of an individual request, it will reduce the overall latency experienced by your users. One example optimization: when you're registering a new user and device, you don't need to make a separate Create Entity call, because the Create Factor call will both create an Entity and a Factor at the same time.
  2. Send your requests to a public Edge Location that is physically closer to where you're requesting from compared to the default US East Coast location. While Verify API does not fully support Edge Locations currently, RTT latency can still be lowered, because the shared Twilio API gateway services that Verify uses supports Edge Locations. Note that using Edge Locations might actually increase latencies when reusing connections, and so you'll need to try and see if this is acceptable. You can switch to an Edge Location by changing the request URL. For example, to send to the Singapore edge, the request AccessTokens URL should be: https://verify.singapore.us1.twilio.com/v2/Services/%service_sid%/AccessTokens

1. How much work is it to implement Verify Push?

1-how-much-work-is-it-to-implement-verify-push page anchor

Your mileage may vary. We've consistently heard that understanding Verify Push is the easy part. The complexity level of your existing apps/backend (e.g. how many places in your UX do you need to insert Verify Push?) is the major driver of the overall amount of work. As general guidance, we suggest budgeting the following amount of time based on feedback from customers who've done it:

  • Setting up the Verify Push Sample App/Backend and understanding how Verify Push works in general takes 1-3 days.
  • Integrating Verify Push as a prototype into your own app(s), backend, and existing login flows takes 1-2 weeks.
  • Getting to production-grade, including testing, could take an additional couple weeks.

1. Testing your backend

1-testing-your-backend page anchor

You can create a mock for the Verify API using OpenAPI specification(link takes you to an external page). You should use the twilio_verify_v2 resources.

You can create a mock for your backend and use the Verify API mock you created for testing your backend. You will have a different URL or environment to use in your apps.

The SDKs communicate directly with the Verify API, so you will need to change the URL to be used in the SDKs. For this, you can create your own NetworkProvider to intercept the SDK request and change the URL.

  1. Implement your own NetworkProvider to change the URL, you can use the NetworkProvider SDK implementation, NetworkAdapter(link takes you to an external page), as a guide
  2. Change the URL before executing the request(link takes you to an external page)
  3. You can pass your own NetworkProvider when building the TwilioVerify instance using the Builder's networkProvider method
  1. Implement your own NetworkProvider to change the URL, you can use the NetworkProvider SDK implementation, NetworkAdapter(link takes you to an external page), as a guide
  2. Change the URL before executing the request(link takes you to an external page)
  3. You can pass your own NetworkProvider when building the TwilioVerify instance using the TwilioVerifyBuilder's setNewtorkProvider method

Change the URL of your app to use the mock or the implementation calling the Verify API mock.


1. Pushes not arriving?

1-pushes-not-arriving page anchor

The Challenge will be created, so to troubleshoot the issue, start by checking your Twilio debugger(link takes you to an external page) to get the error code. Then visit Twilio error codes to understand the issue and possible solutions, e.g.:

  • Error code 52143: Application device token and certificate subject must have the same bundle id

2. Getting an Invalid APNs device token (Error code 52134) for iOS?

2-getting-an-invalid-apns-device-token-error-code-52134-for-ios page anchor

Possible Causes

  • APNs device token format is invalid.
  • Trying to use a development certificate for a production application or vice-versa.

For development signing certificates, e.g. running your app from Xcode with debug build configuration or debugging application, you will need to enable the Sandbox option for your push credential

For distribution signing certificates, e.g. archiving app or running the release build configuration, you will need to disable the Sandbox option for your push credential

3. How do I get notified when a challenge was received by my app?

3-how-do-i-get-notified-when-a-challenge-was-received-by-my-app page anchor

As the push notification implementation is handled by your app, only your app will know when the push notification is received. Your Verify webhook will only receive challenge.approved and challenge.denied events for Challenges, so your backend should provide a way to be notified that a notification for a challenge was received from your app.

4. Using test credentials?

4-using-test-credentials page anchor

Test credentials are not supported for Verify Push.

5. Getting fewer factors than expected for a user from the SDK?

5-getting-fewer-factors-than-expected-for-a-user-from-the-sdk page anchor

The SDK will return the factors stored in the device, so if you call getAllFactors method, you will get only the factors in the device (e.g. 2 factors), and if you have another device (e.g. 3 factors), the user will have 5 factors, but each device will return only the factors stored in the device.

6. Factor deletion or TwilioVerify initialization throwing an error?

6-factor-deletion-or-twilioverify-initialization-throwing-an-error page anchor

The SDK uses Keychain to save the information in a secure way, so Keychain operations could throw an error, for example when deleting a factor (Keychain delete operation) and TwilioVerify initialization (migrating information from one version to a new one). You should implement an alternative flow in case of an error.

Need some help?

Terms of service

Copyright © 2024 Twilio Inc.