Skip to content

Commit

Permalink
update README.md and javadoc with exception explanations
Browse files Browse the repository at this point in the history
  • Loading branch information
lbalmaceda committed Jan 24, 2019
1 parent c6001da commit d878ec0
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 6 deletions.
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -589,11 +589,11 @@ manager.clearCredentials();

### Encryption enforced (Min API 21)

This version expands the minimum version and adds encryption to the data storage. In those devices where a Secure LockScreen has been configured it can require the user authentication before letting them obtain the stored credentials. The class is called `SecureCredentialsManager` and requires at minimum Android API 21.
This version expands the minimum version and adds encryption to the data storage. Additionally, in those devices where a Secure Lock Screen has been configured it can require the user authentication before letting them obtain the stored credentials. The class is called `SecureCredentialsManager` and requires at minimum Android API 21.


#### Usage
The usage is similar to the previous version, with the slight difference that the manager now requires a valid `Context` as shown below:
The usage is similar to the previous version, with the slight difference that the manager now requires a valid android `Context` as shown below:

```java
AuthenticationAPIClient authentication = new AuthenticationAPIClient(account);
Expand All @@ -603,7 +603,7 @@ SecureCredentialsManager manager = new SecureCredentialsManager(this, authentica

#### Requiring Authentication

You can require the user authentication to obtain credentials. This will make the manager prompt the user with the device's configured LockScreen, which they must pass correctly in order to obtain the credentials. **This feature is only available on devices where the user has setup a secured LockScreen** (PIN, Pattern, Password or Fingerprint).
You can require the user authentication to obtain credentials. This will make the manager prompt the user with the device's configured Lock Screen, which they must pass correctly in order to obtain the credentials. **This feature is only available on devices where the user has setup a secured Lock Screen** (PIN, Pattern, Password or Fingerprint).

To enable authentication you must call the `requireAuthentication` method passing a valid _Activity_ context, a Request Code that represents the authentication call, and the title and description to display in the LockScreen. As seen in the snippet below, you can leave these last two parameters with `null` to use the system default resources.

Expand All @@ -614,7 +614,7 @@ private static final int AUTH_REQ_CODE = 11;
manager.requireAuthentication(this, AUTH_REQ_CODE, null, null);
```

When the above conditions are met and the manager requires the user authentication, it will use the activity context to launch a new activity for the result. The outcome of getting approved or rejected by the LockScreen is given back to the activity in the `onActivityResult` method, which your activity must override to redirect the data to the manager using the `checkAuthenticationResult` method.
When the above conditions are met and the manager requires the user authentication, it will use the activity context to launch a new activity for the result. The outcome of getting approved or rejected by the Lock Screen is given back to the activity in the `onActivityResult` method, which your activity must override to redirect the data to the manager using the `checkAuthenticationResult` method.

```java
@Override
Expand All @@ -629,6 +629,15 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
The `checkAuthenticationResult` method will continue the retrieval of credentials on a successful authentication, and the decrypted credentials will be delivered to the callback passed on the `getCredentials` call.


#### Handling exceptions

In the event that something happened while trying to save or retrieve the credentials, a `CredentialsManagerException` will be thrown. These are some of the expected failure scenarios:

- Invalid Credentials format or values. e.g. when it's missing the `access_token`, the `id_token` or the `expires_at` values.
- Tokens have expired but no `refresh_token` is available to perform a refresh credentials request.
- Device's Lock Screen security settings have changed (e.g. the PIN code was changed). Even when `hasCredentials` returns true, the encryption keys will be deemed invalid and until `saveCredentials` is called again it won't be possible to decrypt any previously existing content, since they keys used back then are not the same as the new ones.
- Device is not compatible with some of the algorithms required by the `SecureCredentialsManager` class. This is considered a catastrophic event and might happen when the OEM has modified the Android ROM removing some of the officially included algorithms. Nevertheless, it can be checked in the exception instance itself by calling `isDeviceIncompatible`. By doing so you can decide the fallback for storing the credentials, such as using the regular `CredentialsManager`.

## FAQ

* Why is the Android Lint _error_ `'InvalidPackage'` considered a _warning_?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import android.util.Base64;
import android.util.Log;

import com.auth0.android.Auth0Exception;
import com.auth0.android.authentication.AuthenticationAPIClient;
import com.auth0.android.authentication.AuthenticationException;
import com.auth0.android.callback.AuthenticationCallback;
Expand Down Expand Up @@ -130,7 +131,8 @@ public boolean checkAuthenticationResult(int requestCode, int resultCode) {
* Saves the given credentials in the Storage.
*
* @param credentials the credentials to save.
* @throws CredentialsManagerException if the credentials couldn't be encrypted. If the class is not supported by this device the cause will be a {@link IncompatibleDeviceException}.
* @throws CredentialsManagerException if the credentials couldn't be encrypted. Some devices are not compatible at all with the cryptographic
* implementation and will have {@link CredentialsManagerException#isDeviceIncompatible()} return true.
*/
public void saveCredentials(@NonNull Credentials credentials) throws CredentialsManagerException {
if ((isEmpty(credentials.getAccessToken()) && isEmpty(credentials.getIdToken())) || credentials.getExpiresAt() == null) {
Expand Down Expand Up @@ -162,7 +164,10 @@ public void saveCredentials(@NonNull Credentials credentials) throws Credentials
}

/**
* Tries to obtain the credentials from the Storage.
* Tries to obtain the credentials from the Storage. The callback's {@link BaseCallback#onSuccess(Object)} method will be called with the result.
* If something unexpected happens, the {@link BaseCallback#onFailure(Auth0Exception)} method will be called with the error. Some devices are not compatible
* at all with the cryptographic implementation and will have {@link CredentialsManagerException#isDeviceIncompatible()} return true.
* <p>
* If a LockScreen is setup and {@link #requireAuthentication(Activity, int, String, String)} was called, the user will be asked to authenticate before accessing
* the credentials. Your activity must override the {@link Activity#onActivityResult(int, int, Intent)} method and call
* {@link #checkAuthenticationResult(int, int)} with the received values.
Expand Down

0 comments on commit d878ec0

Please sign in to comment.