Skip to content

Commit

Permalink
Merge pull request #102 from auth0/add-credential-manager-methods
Browse files Browse the repository at this point in the history
Add hasValidCredentials and clearCredentials to CredentialsManager
  • Loading branch information
lbalmaceda authored Jul 10, 2017
2 parents 1706dda + 2bc0cc4 commit 3f96344
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 2 deletions.
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -468,8 +468,15 @@ authentication
});
```

3. **Retrieve credentials**
Existing credentials will be returned if they are still valid, otherwise the `refresh_token` will be used to attempt to renew them. If the `expires_in` or both the `access_token` and `id_token` values are missing, the method will throw a `CredentialsManagerException`. The same will happen if the credentials have expired and there's no `refresh_token` available.
3. **Check credentials existence**
There are cases were you just want to check if a user session is still valid (i.e. to know if you should present the login screen or the main screen). For convenience we include a `hasValidCredentials` method that can let you know in advance if a non-expired token is available without making an additional network call. The same rules of the `getCredentials` method apply:

```java
boolean authenticated = manager.hasValidCredentials();
```

4. **Retrieve credentials**
Existing credentials will be returned if they are still valid, otherwise the `refresh_token` will be used to attempt to renew them. If the `expires_in` or both the `access_token` and `id_token` values are missing, the method will throw a `CredentialsManagerException`. The same will happen if the credentials have expired and there's no `refresh_token` available.

```java
manager.getCredentials(new BaseCallback<Credentials, CredentialsManagerException>(){
Expand All @@ -484,6 +491,13 @@ manager.getCredentials(new BaseCallback<Credentials, CredentialsManagerException
```


5. **Clear credentials**
When you want to log the user out:

```java
manager.clearCredentials();
```

## 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 @@ -97,6 +97,32 @@ public void onFailure(AuthenticationException error) {
});
}

/**
* Checks if a non-expired pair of credentials can be obtained from this manager.
*/
public boolean hasValidCredentials() {
String accessToken = storage.retrieveString(KEY_ACCESS_TOKEN);
String refreshToken = storage.retrieveString(KEY_REFRESH_TOKEN);
String idToken = storage.retrieveString(KEY_ID_TOKEN);
Long expiresAt = storage.retrieveLong(KEY_EXPIRES_AT);

return !(isEmpty(accessToken) && isEmpty(idToken) ||
expiresAt == null ||
expiresAt <= getCurrentTimeInMillis() && refreshToken == null);
}

/**
* Removes the credentials from the storage if present.
*/
public void clearCredentials() {
storage.remove(KEY_ACCESS_TOKEN);
storage.remove(KEY_REFRESH_TOKEN);
storage.remove(KEY_ID_TOKEN);
storage.remove(KEY_TOKEN_TYPE);
storage.remove(KEY_EXPIRES_AT);
storage.remove(KEY_SCOPE);
}

@VisibleForTesting
Credentials recreateCredentials(String idToken, String accessToken, String tokenType, String refreshToken, Date expiresAt, String scope) {
return new Credentials(idToken, accessToken, tokenType, refreshToken, expiresAt, scope);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,9 @@ public Integer retrieveInteger(@NonNull String name) {
}
return sp.getInt(name, 0);
}

@Override
public void remove(@NonNull String name) {
sp.edit().remove(name).apply();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,11 @@ public interface Storage {
*/
@Nullable
Integer retrieveInteger(@NonNull String name);

/**
* Removes a value from the storage.
*
* @param name the name of the value to remove.
*/
void remove(@NonNull String name);
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
Expand Down Expand Up @@ -94,6 +95,7 @@ public void shouldSaveCredentialsInStorage() throws Exception {
verify(storage).store("com.auth0.token_type", "type");
verify(storage).store("com.auth0.expires_at", expirationTime);
verify(storage).store("com.auth0.scope", "scope");
verifyNoMoreInteractions(storage);
}

@Test
Expand Down Expand Up @@ -319,4 +321,69 @@ public void shouldGetAndFailToRenewExpiredCredentials() throws Exception {
assertThat(exception.getCause(), Is.<Throwable>is(authenticationException));
assertThat(exception.getMessage(), is("An error occurred while trying to use the Refresh Token to renew the Credentials."));
}

@Test
public void shouldClearCredentials() throws Exception {
manager.clearCredentials();

verify(storage).remove("com.auth0.id_token");
verify(storage).remove("com.auth0.access_token");
verify(storage).remove("com.auth0.refresh_token");
verify(storage).remove("com.auth0.token_type");
verify(storage).remove("com.auth0.expires_at");
verify(storage).remove("com.auth0.scope");
verifyNoMoreInteractions(storage);
}

@Test
public void shouldHaveCredentialsWhenTokenHasNotExpired() throws Exception {
long expirationTime = CredentialsMock.CURRENT_TIME_MS + 123456L * 1000;
when(storage.retrieveLong("com.auth0.expires_at")).thenReturn(expirationTime);

when(storage.retrieveString("com.auth0.id_token")).thenReturn("idToken");
when(storage.retrieveString("com.auth0.access_token")).thenReturn(null);
assertThat(manager.hasValidCredentials(), is(true));

when(storage.retrieveString("com.auth0.id_token")).thenReturn(null);
when(storage.retrieveString("com.auth0.access_token")).thenReturn("accessToken");
assertThat(manager.hasValidCredentials(), is(true));
}

@Test
public void shouldNotHaveCredentialsWhenTokenHasExpiredAndNoRefreshTokenIsAvailable() throws Exception {
long expirationTime = CredentialsMock.CURRENT_TIME_MS; //Same as current time --> expired
when(storage.retrieveLong("com.auth0.expires_at")).thenReturn(expirationTime);
when(storage.retrieveString("com.auth0.refresh_token")).thenReturn(null);

when(storage.retrieveString("com.auth0.id_token")).thenReturn("idToken");
when(storage.retrieveString("com.auth0.access_token")).thenReturn(null);
assertFalse(manager.hasValidCredentials());

when(storage.retrieveString("com.auth0.id_token")).thenReturn(null);
when(storage.retrieveString("com.auth0.access_token")).thenReturn("accessToken");
assertFalse(manager.hasValidCredentials());
}

@Test
public void shouldHaveCredentialsWhenTokenHasExpiredButRefreshTokenIsAvailable() throws Exception {
long expirationTime = CredentialsMock.CURRENT_TIME_MS; //Same as current time --> expired
when(storage.retrieveLong("com.auth0.expires_at")).thenReturn(expirationTime);
when(storage.retrieveString("com.auth0.refresh_token")).thenReturn("refreshToken");

when(storage.retrieveString("com.auth0.id_token")).thenReturn("idToken");
when(storage.retrieveString("com.auth0.access_token")).thenReturn(null);
assertThat(manager.hasValidCredentials(), is(true));

when(storage.retrieveString("com.auth0.id_token")).thenReturn(null);
when(storage.retrieveString("com.auth0.access_token")).thenReturn("accessToken");
assertThat(manager.hasValidCredentials(), is(true));
}

@Test
public void shouldNotHaveCredentialsWhenAccessTokenAndIdTokenAreMissing() throws Exception {
when(storage.retrieveString("com.auth0.id_token")).thenReturn(null);
when(storage.retrieveString("com.auth0.access_token")).thenReturn(null);

assertFalse(manager.hasValidCredentials());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,16 @@ public void shouldRetrieveIntegerValueFromPreferences() throws Exception {
assertThat(value, is(123));
}


//Remove

@SuppressWarnings("ConstantConditions")
@Test
public void shouldRemovePreferencesKey() throws Exception {
SharedPreferencesStorage storage = new SharedPreferencesStorage(context);
storage.remove("name");
verify(sharedPreferencesEditor).remove("name");
verify(sharedPreferencesEditor).apply();
}

}

0 comments on commit 3f96344

Please sign in to comment.