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 Android 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. Refer to the following figures for an example.

14281428 14281428

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.

19201920

Link the OIDC app with the authentication widget

19061906

How it works?

12251225

Integrate authentication widget with mobile app

The authentication client must have a configuration to interact with the CyberArk Identity Server. The Android app redirects the user to Authentication Widget for authentication. To request authorization, the Android app must redirect the user (browser) to make a secure HTTP call to the authorization endpoint with the following parameters.

Step 1: Create a builder object as shown below:

val cyberArkAccountBuilder = CyberArkAccountBuilder.Builder()
.systemURL(context.getString(R.string.cyberark_auth_system_url))
.hostURL(context.getString(R.string.cyberark_auth_host_url))
.clientId(context.getString(R.string.cyberark_auth_client_id))
.appId(context.getString(R.string.cyberark_auth_app_id))
.responseType(context.getString(R.string.cyberark_auth_response_type))
.scope(context.getString(R.string.cyberark_auth_scope))
.state(context.getString(R.string.cyberark_auth_state))
.redirectUri(context.getString(R.string.cyberark_auth_redirect_uri))
.build()
val cyberArkAccountBuilder = CyberArkAuthWidgetBuilder.Builder()
.systemURL(systemUrl.toString())
.hostURL(widgetHostUrl.toString())
.widgetId(widgetId.toString())
.resourceURL(resourceUrl.toString())
.build()

Step 2: Set up a view model and start the authentication widget flow

Use the CyberArkAuthProvider class, and the CyberArkAccountBuilder, CyberArkAuthWidgetBuilder parameters to set up a view model and start the authentication widget flow. The start authentication widget flow pattern is as follows:

val authResponseHandler: LiveData<ResponseHandler<String>> =
    CyberArkAuthProvider.authWidgetLogin(cyberArkAccountBuilder)
        .start(this, cyberArkAuthWidgetBuilder)
Authentication widget response handler
authWidgetResponseHandler.observe(this, {
          when (it.status) {
              ResponseStatus.SUCCESS -> {// Initiate authorize endpoint
              }
              ResponseStatus.ERROR -> {
              }
              ResponseStatus.LOADING -> {
              }
          }
    })

Step 3: Set up a view model and initiate authorize endpoint

Use the CyberArkAuthProvider class, and the CyberArkAccountBuilder parameter to set up a view model and start the authorization endpoint. The start authorization endpoint flow pattern is as follows:

val authResponseHandler: LiveData<ResponseHandler<AuthCodeFlowModel>> =
                CyberArkAuthProvider.login(cyberArkAccountBuilder).start(this)

Step 4: Declare the observer instance that will receive the authentication result

authResponseHandler.observe(this, {
          when (it.status) {
              ResponseStatus.SUCCESS -> {
// Save access token, refresh token and Id token in Shared Preference using keystore encryption
              }
              ResponseStatus.ERROR -> {
              }
              ResponseStatus.LOADING -> {
              }
          }
    })

Step 5: Launch the authentication widget URL in a Custom Tab

The Identity Android 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.

653653

Step 6: 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:

KeyStoreProvider.get().saveAuthToken(it.data!!.access_token)
KeyStoreProvider.get().saveRefreshToken(it.data!!.refresh_token)
KeyStoreProvider.get().saveIdToken(it.data!!.id_token)

Step 7: Verify token expiry from the access token

Decode the access token to get the expiry time of the token. The following code sample validates and returns the status of the existing access token.

val status = JWTUtils.isAccessTokenExpired(accessTokenData)

Step 8: 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 9: 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 10: Retrieve User Info using the Access token

Use the CyberArkAuthProvider class, and the CyberArkAccountBuilder parameter to set up a view model and start the retrieve user info flow. The retrieve user info flow pattern is as follows:

val authResponseHandler: LiveData<ResponseHandler<UserInfoModel>> =
    CyberArkAuthProvider.userInfo(cyberArkAccountBuilder)
        .start(this, accessTokenData)