Add authentication and authorization using OIDC protocol

This topic describes how to integrate the authentication and authorization flow using the OIDC Authorization code with PKCE grant into the mobile app using the Android SDK

Integrate the authentication and authorization flow using the OIDC Authorization code with PKCE grant into your mobile app using the Android SDK.

As prerequisites, setup the OpenID connect custom app

📘

The Redirect URI for OpenID connect should be "{auth_scheme}://{auth_host}/android/{YOUR_APP_PACKAGE_NAME}/redirectURICallback"

How it works?

Integrate the OIDC flow using the android SDK

Step 1: Create a builder object as shown below:

val cyberArkAccountBuilder = CyberArkAccountBuilder.Builder()
    .systemURL(getString(R.string.cyberark_account_system_url))
    .hostURL(getString(R.string.cyberark_account_host_url))
    .clientId(getString(R.string.cyberark_account_client_id))
    .appId(getString(R.string.cyberark_account_app_id))
    .responseType(getString(R.string.cyberark_account_response_type))
    .scope(getString(R.string.cyberark_account_scope))
    .redirectUri(getString(R.string.cyberark_account_redirect_uri))
    .build()

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

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

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

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

authResponseHandler.observe(this, {
          when (it.status) {
              ResponseStatus.SUCCESS -> {
              }
              ResponseStatus.ERROR -> {
              }
              ResponseStatus.LOADING -> {
              }
          }
    })

Step 4: Launch the authorized 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.

Step 5: Use device storage for access, refresh and ID tokens

Save the access token and/or refresh 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 6: 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 7: 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 8: 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 9: Retrieve User Info using 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)