Auth0.Android Save and Renew Tokens

When an authentication is performed with the offline_access scope included, it returns a refresh token that can be used to request a new user token, without forcing the user to perform authentication again.

Credentials Manager

Auth0.Android provides a utility class to streamline the process of storing and renewing credentials. You can access the accessToken or idToken properties from the Credentials instance. This is the preferred method to manage user credentials.

Credential Managers are included as part of the Auth0.Android SDK. If this is not yet part of your dependencies, follow the instructions in Auth0.Android.

There are two classes you can use to manage credentials:

  • CredentialsManager stores data in plain text.

  • SecureCredentialsManager encrypts the data before storing it, using a combination of RSA and AES algorithms along with Android KeyStore.

Using the CredentialsManager class

Set up the CredentialsManager

Create a new instance by passing an AuthenticationAPIClient and a Storage implementation.

val auth0 = Auth0(this)
val apiClient = AuthenticationAPIClient(auth0)
val manager = CredentialsManager(apiClient, SharedPreferencesStorage(this))

Current state of the authentication

Stored credentials are considered valid if they have not expired or can be refreshed. Check if a user has already logged in.

val loggedIn = manager.hasValidCredentials()

To log the user out of your application, remove the stored credentials and direct them to the login screen.

manager.clearCredentials()

Retrieving credentials

Because the credentials may need to be refreshed against Auth0 Servers, this method is asynchronous. Pass a callback implementation where you want to receive the credentials. Credentials returned by this method upon success are always valid.

manager.getCredentials(object: Callback<Credentials, CredentialsManagerException>() {
    override fun onSuccess(credentials: Credentials) {
        // Use credentials
    }

    override fun onFailure(error: CredentialsManagerException) {
        // No credentials were previously saved or they couldn't be refreshed
    }
})

If the accessToken has expired, the manager automatically uses the refreshToken and renews the credentials for you. New credentials will be stored for future access.

Save new credentials

You can save the credentials obtained during authentication in the manager.

manager.saveCredentials(credentials)

Using the SecureCredentialsManager class

Set up the SecureCredentialsManager

Create a new instance by passing a valid android Context, an AuthenticationAPIClient and a Storage implementation.

val auth0 = Auth0(this)
val apiClient = AuthenticationAPIClient(auth0)
val manager = SecureCredentialsManager(this, apiClient, SharedPreferencesStorage(this))

The methods to obtain, save, check for existence, and clear the credentials are the same as described in the section above.

Pre-authenticate the user

This class provides optional functionality for additional authentication using the device's configured lock screen.

If Lock Screen Security is set to something different than PIN, Pattern, Password or Fingerprint, this feature isn't available.

Call the method below to enable the authentication. Pass a valid Activity context, a request code, and two optional strings to use as title and description for the lock screen.

Also define a request code constant so that the request code coming from the activity result can be matched up.

companion object {
  const val RC_UNLOCK_AUTHENTICATION = 123
}

// Called from an Activity
val available = manager.requireAuthentication(this, RC_UNLOCK_AUTHENTICATION, getString(R.string.unlock_authentication_title), getString(R.string.unlock_authentication_description))

If the feature is enabled, the manager will prompt the user to authenticate using the configured lock screen. The result of this call will be obtained in the onActivityResult method of the activity passed before as first parameter. If the feature was not enabled, lock screen authentication will be skipped.

After checking that the received request code matches the one used in the configuration step, redirect the received parameters to the manager to finish the authentication. The credentials will yield to the original callback.

override fun onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == RC_UNLOCK_AUTHENTICATION && manager.checkAuthenticationResult(requestCode, resultCode)) {
        return
    }

    super.onActivityResult(requestCode, resultCode, data)
}

The onActivityResult method was deprecated on 2021 in favor of the new Activity Result APIs. However, the Auth0.Android SDK is not compatible with these contracts. You can continue to use the deprecated methods safely.

Handling usage exceptions

If an unexpected event occurs while trying to save or retrieve the Credentials, a CredentialsManagerException will be thrown. These are some of the failure scenarios you can expect:

  • The Credentials to be stored are invalid (for example, some of the following fields are not defined: access_token, id_token or expires_at).

  • The stored Credentials have expired but there is no refresh token available to renew them automatically.

  • The device's lock screen security settings have changed (for example the security PIN code changed). Even when hasCredentials returns true, the encryption keys will be deemed invalid. Until saveCredentials is called again, it won't be possible to decrypt any previously existing content because they previously used keys are not the same as the new ones.

  • The device is not compatible with some of the cryptography algorithms required by the SecureCredentialsManager class. This is considered a catastrophic event and is the only exception that will prevent you from using this implementation. This scenario happens when the OEM has modified the Android ROM of the device, removing some of the algorithms officially included in every Android distribution. Nevertheless, you can check if this is the case in the exception instance itself by calling the isDeviceIncompatible method. By doing so you can decide the fallback implementation for storing the credentials, such as using the regular CredentialsManager class.