Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch Key alias migration for Secure Credentials Manager #325

Merged
merged 3 commits into from
Aug 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ public class SecureCredentialsManager {
private static final String KEY_CREDENTIALS = "com.auth0.credentials";
private static final String KEY_EXPIRES_AT = "com.auth0.credentials_expires_at";
private static final String KEY_CAN_REFRESH = "com.auth0.credentials_can_refresh";
private static final String KEY_ALIAS = "com.auth0.key";
private static final String KEY_CRYPTO_ALIAS = "com.auth0.manager_key_alias";
@VisibleForTesting
static final String KEY_ALIAS = "com.auth0.key";

private final AuthenticationAPIClient apiClient;
private final Storage storage;
Expand Down Expand Up @@ -165,6 +167,7 @@ public void saveCredentials(@NonNull Credentials credentials) throws Credentials
storage.store(KEY_CREDENTIALS, encryptedEncoded);
storage.store(KEY_EXPIRES_AT, expiresAt);
storage.store(KEY_CAN_REFRESH, canRefresh);
storage.store(KEY_CRYPTO_ALIAS, KEY_ALIAS);
} catch (IncompatibleDeviceException e) {
throw new CredentialsManagerException(String.format("This device is not compatible with the %s class.", SecureCredentialsManager.class.getSimpleName()), e);
} catch (CryptoException e) {
Expand Down Expand Up @@ -211,6 +214,7 @@ public void clearCredentials() {
storage.remove(KEY_CREDENTIALS);
storage.remove(KEY_EXPIRES_AT);
storage.remove(KEY_CAN_REFRESH);
storage.remove(KEY_CRYPTO_ALIAS);
Log.d(TAG, "Credentials were just removed from the storage");
}

Expand All @@ -223,9 +227,10 @@ public boolean hasValidCredentials() {
String encryptedEncoded = storage.retrieveString(KEY_CREDENTIALS);
Long expiresAt = storage.retrieveLong(KEY_EXPIRES_AT);
Boolean canRefresh = storage.retrieveBoolean(KEY_CAN_REFRESH);
return !(isEmpty(encryptedEncoded) ||
expiresAt == null ||
expiresAt <= getCurrentTimeInMillis() && (canRefresh == null || !canRefresh));
String keyAliasUsed = storage.retrieveString(KEY_CRYPTO_ALIAS);
return KEY_ALIAS.equals(keyAliasUsed) &&
!(isEmpty(encryptedEncoded) || expiresAt == null ||
expiresAt <= getCurrentTimeInMillis() && (canRefresh == null || !canRefresh));
}

private void continueGetCredentials(final BaseCallback<Credentials, CredentialsManagerException> callback) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ public void shouldSaveRefreshableCredentialsInStorage() {
verify(storage).store(eq("com.auth0.credentials"), stringCaptor.capture());
verify(storage).store("com.auth0.credentials_expires_at", sharedExpirationTime);
verify(storage).store("com.auth0.credentials_can_refresh", true);
verify(storage).store("com.auth0.manager_key_alias", SecureCredentialsManager.KEY_ALIAS);
verifyNoMoreInteractions(storage);
final String encodedJson = stringCaptor.getValue();
assertThat(encodedJson, is(notNullValue()));
Expand Down Expand Up @@ -155,6 +156,7 @@ public void shouldSaveRefreshableCredentialsUsingAccessTokenExpForCacheExpiratio
verify(storage).store(eq("com.auth0.credentials"), stringCaptor.capture());
verify(storage).store("com.auth0.credentials_expires_at", accessTokenExpirationTime);
verify(storage).store("com.auth0.credentials_can_refresh", true);
verify(storage).store("com.auth0.manager_key_alias", SecureCredentialsManager.KEY_ALIAS);
verifyNoMoreInteractions(storage);
final String encodedJson = stringCaptor.getValue();
assertThat(encodedJson, is(notNullValue()));
Expand Down Expand Up @@ -183,6 +185,7 @@ public void shouldSaveRefreshableCredentialsUsingIdTokenExpForCacheExpirationInS
verify(storage).store(eq("com.auth0.credentials"), stringCaptor.capture());
verify(storage).store("com.auth0.credentials_expires_at", idTokenExpirationTime);
verify(storage).store("com.auth0.credentials_can_refresh", true);
verify(storage).store("com.auth0.manager_key_alias", SecureCredentialsManager.KEY_ALIAS);
verifyNoMoreInteractions(storage);
final String encodedJson = stringCaptor.getValue();
assertThat(encodedJson, is(notNullValue()));
Expand Down Expand Up @@ -210,6 +213,7 @@ public void shouldSaveNonRefreshableCredentialsInStorage() {
verify(storage).store(eq("com.auth0.credentials"), stringCaptor.capture());
verify(storage).store("com.auth0.credentials_expires_at", expirationTime);
verify(storage).store("com.auth0.credentials_can_refresh", false);
verify(storage).store("com.auth0.manager_key_alias", SecureCredentialsManager.KEY_ALIAS);
verifyNoMoreInteractions(storage);
final String encodedJson = stringCaptor.getValue();
assertThat(encodedJson, is(notNullValue()));
Expand Down Expand Up @@ -573,6 +577,7 @@ public void shouldClearCredentials() {
verify(storage).remove("com.auth0.credentials");
verify(storage).remove("com.auth0.credentials_expires_at");
verify(storage).remove("com.auth0.credentials_can_refresh");
verify(storage).remove("com.auth0.manager_key_alias");
verifyNoMoreInteractions(storage);
}

Expand All @@ -586,6 +591,7 @@ public void shouldHaveCredentialsWhenTokenHasNotExpired() {
when(storage.retrieveLong("com.auth0.credentials_expires_at")).thenReturn(expirationTime);
when(storage.retrieveBoolean("com.auth0.credentials_can_refresh")).thenReturn(false);
when(storage.retrieveString("com.auth0.credentials")).thenReturn("{\"id_token\":\"idToken\"}");
when(storage.retrieveString("com.auth0.manager_key_alias")).thenReturn(SecureCredentialsManager.KEY_ALIAS);
assertThat(manager.hasValidCredentials(), is(true));

when(storage.retrieveString("com.auth0.credentials")).thenReturn("{\"access_token\":\"accessToken\"}");
Expand All @@ -598,6 +604,7 @@ public void shouldNotHaveCredentialsWhenTokenHasExpiredAndNoRefreshTokenIsAvaila
when(storage.retrieveLong("com.auth0.credentials_expires_at")).thenReturn(expirationTime);
when(storage.retrieveBoolean("com.auth0.credentials_can_refresh")).thenReturn(false);
when(storage.retrieveString("com.auth0.credentials")).thenReturn("{\"id_token\":\"idToken\"}");
when(storage.retrieveString("com.auth0.manager_key_alias")).thenReturn(SecureCredentialsManager.KEY_ALIAS);
assertThat(manager.hasValidCredentials(), is(false));

when(storage.retrieveString("com.auth0.credentials")).thenReturn("{\"access_token\":\"accessToken\"}");
Expand All @@ -610,6 +617,7 @@ public void shouldHaveCredentialsWhenTokenHasExpiredButRefreshTokenIsAvailable()
when(storage.retrieveLong("com.auth0.credentials_expires_at")).thenReturn(expirationTime);
when(storage.retrieveBoolean("com.auth0.credentials_can_refresh")).thenReturn(true);
when(storage.retrieveString("com.auth0.credentials")).thenReturn("{\"id_token\":\"idToken\", \"refresh_token\":\"refreshToken\"}");
when(storage.retrieveString("com.auth0.manager_key_alias")).thenReturn(SecureCredentialsManager.KEY_ALIAS);
assertThat(manager.hasValidCredentials(), is(true));

when(storage.retrieveString("com.auth0.credentials")).thenReturn("{\"access_token\":\"accessToken\", \"refresh_token\":\"refreshToken\"}");
Expand All @@ -619,10 +627,37 @@ public void shouldHaveCredentialsWhenTokenHasExpiredButRefreshTokenIsAvailable()
@Test
public void shouldNotHaveCredentialsWhenAccessTokenAndIdTokenAreMissing() {
when(storage.retrieveString("com.auth0.credentials")).thenReturn("{\"token_type\":\"type\", \"refresh_token\":\"refreshToken\"}");
when(storage.retrieveString("com.auth0.manager_key_alias")).thenReturn(SecureCredentialsManager.KEY_ALIAS);

assertFalse(manager.hasValidCredentials());
}

@Test
public void shouldNotHaveCredentialsWhenTheAliasUsedHasNotBeenMigratedYet() {
long expirationTime = CredentialsMock.CURRENT_TIME_MS + 123456L * 1000;
when(storage.retrieveLong("com.auth0.credentials_expires_at")).thenReturn(expirationTime);
when(storage.retrieveBoolean("com.auth0.credentials_can_refresh")).thenReturn(false);
when(storage.retrieveString("com.auth0.credentials")).thenReturn("{\"id_token\":\"idToken\"}");
when(storage.retrieveString("com.auth0.manager_key_alias")).thenReturn("old_alias");
assertThat(manager.hasValidCredentials(), is(false));

when(storage.retrieveString("com.auth0.credentials")).thenReturn("{\"access_token\":\"accessToken\"}");
assertThat(manager.hasValidCredentials(), is(false));
}

@Test
public void shouldNotHaveCredentialsWhenTheAliasUsedHasNotBeenSetYet() {
long expirationTime = CredentialsMock.CURRENT_TIME_MS + 123456L * 1000;
when(storage.retrieveLong("com.auth0.credentials_expires_at")).thenReturn(expirationTime);
when(storage.retrieveBoolean("com.auth0.credentials_can_refresh")).thenReturn(false);
when(storage.retrieveString("com.auth0.credentials")).thenReturn("{\"id_token\":\"idToken\"}");
when(storage.retrieveString("com.auth0.manager_key_alias")).thenReturn(null);
assertThat(manager.hasValidCredentials(), is(false));

when(storage.retrieveString("com.auth0.credentials")).thenReturn("{\"access_token\":\"accessToken\"}");
assertThat(manager.hasValidCredentials(), is(false));
}

/*
* Authentication tests
*/
Expand Down Expand Up @@ -860,6 +895,7 @@ private String insertTestCredentials(boolean hasIdToken, boolean hasAccessToken,
when(storage.retrieveString("com.auth0.credentials")).thenReturn(encoded);
when(storage.retrieveLong("com.auth0.credentials_expires_at")).thenReturn(willExpireAt != null ? willExpireAt.getTime() : null);
when(storage.retrieveBoolean("com.auth0.credentials_can_refresh")).thenReturn(hasRefreshToken);
when(storage.retrieveString("com.auth0.manager_key_alias")).thenReturn(SecureCredentialsManager.KEY_ALIAS);
return storedJson;
}

Expand Down