Integrate authentication widget for strong MFA
This topic describes how to integrate the authentication widget along with OIDC Authorization PKCE grant into the mobile app using the iOS SDK
Provide an authentication and authorization flow with strong MFA and self-service registration by embedding the authentication widget into the SDK's Android mobile app.
Prerequisites
Step 1: Setup the OpenID connect custom app
Step 2: Create authentication rule
Create an authentication rule that challenges the user to authenticate with MFA when the mobile app requests it. Refer to the following link for steps and instructions for creating an authentication rule in the Admin Portal.
https://docs.cyberark.com/Product-Doc/OnlineHelp/Idaptive/Latest/en/Content/CoreServices/Authenticate/MFA-AdminPortal.htm
To find your authentication Policies in the Admin Portal, navigate Core Services > Policies > Authentication Policy.
Step 3: Configure authentication Widget:
Please refer to https://docs.cyberark.com/Product-Doc/OnlineHelp/idaptive/Latest/en/Content/Widgets/Create-Authentication-Widget.htm to get information on how to use widgets
To find your authentication widgets in the Admin Portal, navigate to Web apps > Widgets. Refer to the following figures for an example.
Link the OIDC app with the authentication widget
How it works?
Integrate authentication widget with mobile app
The authentication client must have a configuration to interact with the CyberArk Identity Server. The iOS app redirects the user to Authentication Widget for authentication. The iOS app must redirect the user (browser) to make a secure HTTP call to the authorization endpoint with the following parameters to request authorization.
Step 1: Add the URL Scheme to the project
Define a callback (redirect and resource URL scheme) in the app, which helps the app to exchange the authorization codes for access tokens. To add the callback URL scheme, refer to the following steps:
- Goto Xcode, select the root project >> target >> Info
- Expand the URL Types section and set the Identifier value to $(PRODUCT_BUNDLE_IDENTIFIER) and URL Scheme to a unique URL scheme with the desired name.

Step 2: Create a builder object as shown below:
guard let config = plistValues(bundle: Bundle.main, plistFileName: "IdentityConfiguration") else { return }
//CyberarkAccount
guard let account = CyberArkAuthProvider.webAuth()?
.set(clientId: config.clientId)
.set(domain: config.domain)
.set(redirectUri: config.redirectUri)
.set(applicationID: config.applicationID)
.set(presentingViewController: self)
.setCustomParam(key: "", value: "")
.set(scope: config.scope)
.set(webType: .sfsafari)
.set(systemURL: config.systemurl)
.set(authWidgetHostURL: config.authwidgethosturl)
.set(authWidgetID: config.authwidgetId)
.set(authWidgetResourceURL: config.authwidgetresourceURL)
.build() else { return }
CyberArkAuthProvider.launchAuthWidget(account: account)
Step 3: Define a callback to receive the widget response
func addAuthWidgetResourceURLObserver(){
CyberArkAuthProvider.didReceiveResurceURLCallback = { (status, message) in
if status {
DispatchQueue.main.async {
self.dismiss(animated: true) {
self.doLogin()
}
}
} else {
DispatchQueue.main.async {
self.dismiss(animated: true) {
self.showAlert(message: message)
}
}
}
}
Step 4: Launch the authentication widget URL in a Safari view controller
The Identity iOS SDK is enabled with the ability to open the CyberArk Identity sign-in web page to perform the user authentication in a browser window.
After authentication, the app redirects the user back to the app to exchange the received authorization code for an access token and/or refresh token.

Step 5: Use device storage for access, refresh, and ID tokens
Save the access token, refresh token, and ID token in device storage (SharedPreference) using Keystore encryption.
The Keystore encryption model is as follows:
KeyChainWrapper.standard.save(key: KeyChainStorageKeys.accessToken.rawValue, data: accessToken.toData() ?? Data())
}
KeyChainWrapper.standard.save(key: KeyChainStorageKeys.refreshToken.rawValue, data: refreshToken.toData() ?? Data())
}
let date = Date().epirationDate(with: expiresIn)
KeyChainWrapper.standard.save(key: KeyChainStorageKeys.access_token_expiresIn.rawValue, data: Data.init(from: date))
Step 6: To get Refresh the token
Use the refresh token to obtain a new access token.
val refreshTokenResponseHandler: LiveData<ResponseHandler<RefreshTokenModel>> =
CyberArkAuthProvider.refreshToken(cyberArkAccountBuilder).start(this, refreshTokenData)
Refer to Refresh Token for details.
Step 7: Obtain User Info from the ID token
An ID token is an artifact that confirms that the user has been authenticated. An ID Token is a JWT Token, which is a cryptographically signed Base64-encoded JSON object. Here is an example of the decoded ID token
ID Token Payload:
{
"auth_time": <authentication_time>,
"is": "<issuer_identifier>",
"given_name": "<user_name>",
"iat": <ID_token_issued_time>,
"aud": "<audience_this_ID_token_is_intended_for>",
"name": "<user_name>",
"email": "<user_email_address>",
"family_name": "<user_name>",
"preferred_username": "<user_name>",
"unique_name": "<user_name>",
"exp": <ID_token_expiry_time>,
"sub": "<An_identifier_for_user>",
"email_verified":
}
Step 8: Retrieve User Info using the Access token
Use the CyberArkAuthProvider class to retrieve user info flow. The retrieve user info flow pattern is as follows:
guard let config = plistValues(bundle: Bundle.main, plistFileName: "IdentityConfiguration") else { return }
//CyberarkAccount
guard let account = CyberArkAuthProvider.webAuth()?
.set(clientId: config.clientId)
.set(domain: config.domain)
.set(redirectUri: config.redirectUri)
.set(applicationID: config.applicationID)
.set(presentingViewController: self)
.setCustomParam(key: "", value: "")
.set(scope: config.scope)
.set(webType: .sfsafari)
.set(systemURL: config.systemurl)
.build() else { return }
CyberArkAuthProvider.fetchUserInfo()
Step 9: Define a callback to receive the user info response
func addObserver(){
CyberArkAuthProvider.didReceiveUserInfo = { (status, message, response) in
DispatchQueue.main.async {
self.activityIndicator.stopAnimating()
if status {
self.setup(info: response)
} else {
self.showAlert(message: message)
}
}
}
}
Updated 9 months ago