Use the Devices SDK to enable your app to verify the identity of a user by responding to notifications from a custom authenticator.
To set up and configure your app:
Add the SDK to your app Configure the required capabilities Register for notifications Initialize the SDK client Next, register the device to receive identity verification notifications for the custom authenticator. Your app needs to support a user sign-in flow and request the correct permissions or scopes. Once the end user enrolls the device, the app can respond to user verification notifications (challenges).
If needed, you can also unenroll the device, either locally, or both locally and on the server.
Note: The iOS code snippets assume that there's a singleton class called DeviceSDKManager
that manages interactions with the Devices SDK. The singleton contains any required state information, such as the following:
The current SDK client The APNs token for the current launch of the app Utility functions Your app may use a different way to interact with the Devices SDK.
The following image shows how data flows through the Devices SDK:
Enable the user to sign in A valid user account authentication token is necessary to add a device as an authenticator. To get the token, first enable the user to sign in to their account using the Okta mobile Swift SDK (opens new window) or if you're already using it, the Okta IDX Swift SDK (opens new window) . For more information on signing users in to your app, see Sign users in to your mobile app using the redirect model (opens new window) .
Then add the extra permissions that the Devices SDK requires to the access token. Add the following strings to the space-delimited list of scopes in the Okta.plist
file:
okta.myAccount.appAuthenticator.manage
okta.myAccount.appAuthenticator.read
If you're initializing the scopes in your app's code instead of using the Okta.plist
file, update that code using the scopes as strings.
Add Devices SDK to your app Install from CocoaPods (opens new window) . Add the following lines to your Podfile to load the SDK for each target that uses the SDK replacing MyApplicationTarget
with the name of the target:
The source for the Okta Swift Devices SDK is in the Okta GitHub repository:
https://github.com/okta/okta-devices-swift.
There are two ways for your app to receive notifications from a custom authenticator:
As a push notification that's delivered whether your app is closed, in the background, or in the foreground As a request for any queued notifications when your app is in the foreground Although your app doesn't need to receive push notifications to use the Devices SDK, we suggest that you do this for the best user experience. To receive notifications, add the push notification capability to your app. At runtime, register your app with the notification manager, and retrieve the current APNs token. Use this token in the next step.
For more information, see Registering Your App with APNs (opens new window) in Apple developer documentation. The examples in this guide assume that the end user registered the app to receive notifications.
The token is returned by the system in application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
(opens new window) . Use a property to store the token, though don't save the token between app launches as it can change. If there's an error registering for notifications, the system calls application(_:didFailToRegisterForRemoteNotificationsWithError:)
(opens new window) . In this case, your app can still load undelivered challenges .
Add an app group capability to your app if it doesn't already have one. You'll use the group identifier in the next step. See Configuring App Groups (opens new window) in the Apple developer documentation.
Initialize the client You must initialize the SDK client when your app launches as it configures some push notification settings. The following function is an example of configuring and initializing the client that's called from application(_:didFinishLaunchingWithOptions:)
(opens new window) . The call can go before or after the code to register for push notifications that you added earlier.
Use the name of the group that you included when you added the app group capability earlier. The compiler conditional ensures that Device Authenticator uses the appropriate APNs environment.
Register the device To use the device to verify the identity of a user it must be registered, or enrolled , with the custom authenticator.
To enroll a device, you need:
An app that enables a user to sign in to their account The appropriate scopes. See Enable the user to sign in . A configured and enabled custom authenticator in your Okta org The current APNs token if your app is registered for push notifications Alternatively, you can enroll the device by using the MyAccount app authenticators API (opens new window) .
There are many different ways that your app may start the flow for enrolling a device, such as the user setting a preference or adding an authentication method. No matter how the enrollment flow starts, it follows the same steps:
Sign the user in if they're currently signed out. Create the configuration for the authenticator. Create the enrollment details. Call enroll(authenticationToken:authenticatorConfig:enrollmentParameters:)
. Handle the result of the call in the completion block. Configuring enrollment requires two different tokens. One is the access token that is provided by Okta after the user signs in. The other is the APNs token that is returned after you register for push notifications.
The following function is an example of enrolling a device. It assumes that the user has already signed in using the Okta Mobile SDK for Swift (opens new window) :
If your app isn't configured to receive push notifications or the device token isn't available yet, use a value of DeviceToken.empty
for the deviceToken
property of EnrollmentParameters
.
Update the push notification token The APNs token that's returned to your app after it registers for push notifications may be different on each app launch. Update the token in all the accounts that use this device for authentication each time you receive one. This is an example function that updates the enrollments. Call it from application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
(opens new window) :
The function assumes a valid access token. In a production app, consider adding a function that either updates the token if it's invalid, or gets a new token using a user sign-in flow.
Alternatively, you can update the registration token by using the MyAccount app authenticators API (opens new window) .
Unenroll the device You may need to unenroll a device from a user account. For example, your app may enable a user to turn off notifications using a setting. It's also possible to unenroll the device on the server, such as an administrator removing an account. One way to detect if the device is unenrolled on the server is that a call to either unenroll the device or to retrieve undelivered notifications results in an error of type serverAPIError
.
The following function is an example of unenrolling the device either locally, or both locally and on the server. It assumes a valid authentication token:
Alternatively, you can delete an enrollment by using the MyAccount app authenticators API (opens new window) .
Process a custom authenticator notification When the custom authenticator is used during a sign-in attempt, Okta creates a push challenge , a notification that requests the user to verify their identity. This challenge is sent to the user's enrolled devices.
Specify action titles when you initialize the client to enable actionable notifications. The titles are the names of the different selections that appear when a user taps and holds a notification. The following code shows the additional lines for the initOktaDeviceAuthenticator()
shown in Initialize the client :
The first two titles are the actions for the notification that requests a user to approve or deny that they're trying to sign in. The third is the action for a biometric verification. Replace YourAppName
with the name of your app, which you can read from the CFBundleName
key of the Info.plist
file in your main bundle.
Check for a challenge When a notification arrives the first step is to check if it's a Devices SDK challenge. Call the appropriate Devices SDK function to create a PushChallengeProtocol
from the notification. If the result is an object, continue processing the challenge. If it's nil
then the notification isn't part of the Devices SDK.
Use parsePushNotificationResponse(_:allowedClockSkewInSeconds:)
when a notification arrives when your app is in the background or inactive. Use parsePushNotification(_:allowedClockSkewInSeconds:)
when a notification arrives when your app is in the foreground. The allowedClockSkewInSeconds
parameter is optional. The following code shows handling a notification that's sent when the app is inactive:
Handle a challenge The push challenge includes the steps, or remediations , required to validate the user identity. Your app handles these steps sequentially and updates the SDK with the results. Your app must handle two different types of steps:
Consent: Confirm that the user is attempting to sign in. Message: An informational message, such as the user canceling verification or a key being corrupt or missing. There's also a step for confirming a user's identity with biometrics that is handled by the SDK.
An object of type RemediationStepUserConsent
represents the consent step. An object of type RemediationStepMessage
represents the message step. The following is an example of handling the different cases:
If you enabled actionable notifications by providing action titles and the user selected an action, the Devices SDK handles the consent step. When this happens, the call to resolve
doesn't return a consent step.
Your app must implement a UI for the user to respond to a user consent notification even if you provide titles for the notification actions. For example, a user may only tap the notification to go directly to your app instead of selecting an action. However you determine the user's choice, the last step is to enable the Devices SDK to inform the server by calling provide(_)
:
Alternatively, you can respond to a challenge by using the MyAccount app authenticators API (opens new window) .
Load undelivered challenges The server queues undelivered notifications for delivery later. When your app launches or comes into the foreground, check for undelivered notifications and process them as appropriate. The following is an example function to retrieve Devices SDK notifications that you can call from applicationDidBecomeActive(_:)
(opens new window) :
The code assumes that each enrollment uses the same access token. Use the appropriate access token if your app handles multiple user accounts.
Alternatively, you can retrieve undelivered challenges by using the MyAccount app authenticators API (opens new window) .
Access token management The SDK communicates with an Okta server using the HTTPS protocol and requires an access token for user authentication and authorization. For authentication flows and access token requests, use the latest version of the Okta Swift mobile SDK (opens new window) . To enroll a push authenticator, the user needs to have an access token that contains the okta.myAccount.appAuthenticator.manage
scope. You can also use this scope for the following operations:
Enroll and unenroll user verification keys Update device token for push authenticator enrollment Request pending push challenges Enable and disable CIBA capability for push authenticator enrollment Delete push authenticator enrollment
Note: Applications that use sensitive data shouldn't store or cache access tokens or refresh access tokens that contain the okta.myAccount.appAuthenticator.manage
scope. Instead, reauthenticate the user and get a new access token.
The following is a list of operations that are considered high risk and require reauthentication:
Enroll push authenticator Enable or disable user verification for push authenticator enrollment Delete push authenticator enrollment Maintenance token configuration and usage Other operations are low risk and may not require interactive authentication. For that reason, the Okta Devices SDK provides the silent user reauthentication method, retrieveMaintenanceToken
. This method retrieves a maintenance access token for reauthentication that allows an application to silently perform the following operations:
Request pending push challenges Enable and disable CIBA capability for the push authenticator enrollment Update device tokens for push authenticator enrollment To successfully obtain the maintenance token, you must first configure your Okta OIDC application to support the JWT Bearer grant type:
You can use the Apps API's update app (opens new window) operation (PUT /apps/${appId}
) to modify the settings.oauthClient.grant_types
property array to include the JWT Bearer grant type, urn:ietf:params:oauth:grant-type:jwt-bearer
.
Alternatively, when you use the Admin Console to add or update the OIDC application in a custom authenticator, the application automatically updates with the JWT Bearer grant type. See Add a custom authenticator .
Apps API usage sample Explore the Configure and Use JWT Bearer Grant (opens new window) Postman Collection for API examples of how to do the following:
Get your OIDC app object properties. Update your OIDC app to include the urn:ietf:params:oauth:grant-type:jwt-bearer
grant type. Obtain a token with your OIDC app client ID. Fork this collection and add url
, apiKey
, appId
, and yourClientId
environment variables to run the example endpoints. The PUT
method is a full property-replace operation, so you need to specify all required OIDC app properties, including any previous grant types. See Create an API token to obtain an apiKey
from your org for testing purposes.
Swift maintenance token usage example