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

Add Android P support for SecureCredentialsManager #203

Merged
merged 3 commits into from
Dec 26, 2018
Merged

Add Android P support for SecureCredentialsManager #203

merged 3 commits into from
Dec 26, 2018

Conversation

shriakhilc
Copy link
Contributor

Fixes #187
Please don't merge while WIP. Only writing proper tests is remaining.

Copy link
Contributor

@lbalmaceda lbalmaceda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tested this solution on devices/emulators already? Address the comments and make sure tests are passing and I'll test it here and merge it.

@@ -85,7 +86,15 @@ public CryptoUtil(@NonNull Context context, @NonNull Storage storage, @NonNull S
keyStore.load(null);
if (keyStore.containsAlias(KEY_ALIAS)) {
//Return existing key
return (KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS, null);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move all this block to a new method since you're using the same one a few lines below.

private KeyStore.PrivateKeyEntry getKeyEntryForAlias(KeyStore keyStore, String alias) {
}

I suggested that name since the current method this is in is already named similarly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lbalmaceda I named the method getKeyEntryCompat since it is a wrapper that is only checking the API level to call the appropriate methods.

I figured out a method that gets all the tests to run, and gives no warnings on the emulator (I don't have an Android P device, but I believe it should have the same results). However, it is a bit hackish, so I wanted to run it by you to see if it's ok.

I added a condition to check if the PrivateKey is null at this line. Since I couldn't mimic an empty PrivateKey item despite looking into the source codes of some of the classes, I am simply falling back and using getEntry as before in such cases.

From what I observed, the PrivateKey object is null at that point only during the tests. On devices, the getRSAKeyEntry method generates the entry if the alias is not present in the keystore.

@lbalmaceda
Copy link
Contributor

Looping you in @sebaslogen since you originally reported the issue. Would you mind testing this PR out and giving us feedback? Thanks

@shriakhilc
Copy link
Contributor Author

shriakhilc commented Oct 30, 2018

All the 647 tests in the suite completed successfully when I ran them locally. I'm not sure why Circle CI is showing some failed tests.

@sebaslogen
Copy link

sebaslogen commented Oct 31, 2018

Thanks for the fix. I compiled the library and manually replaced the Auth0 dependency in my project, the app works correctly and I don't see anymore the previous exception KeyStore exception android.os.ServiceSpecificException: (code 7)
So this has my approval. 👍

@lbalmaceda
Copy link
Contributor

Nice! Thanks for the feedback @sebaslogen. I haven't had time to try this locally on my own, but I have been seeing many failed builds for the android repos. I hope I can look into this before eow @TheGamer007 . 🕐

@shriakhilc shriakhilc changed the title WIP: Add Android P support for SecureCredentialsManager Add Android P support for SecureCredentialsManager Nov 3, 2018
@lbalmaceda lbalmaceda added this to the v1-Next milestone Nov 28, 2018
Copy link
Contributor

@lbalmaceda lbalmaceda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few code style changes and I'll merge it. Looks and works fine 👌

Certificate certificate = keyStore.getCertificate(KEY_ALIAS);

if (privateKey == null) {
return (KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS, null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line will have the same value as privateKey. Seems like this will always return null, am I correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the privateKey is null, the constructor can't be used to create a PrivateKeyEntry object and it throws a NullPointerException. But the method here returns a PrivateKeyEntry object that contains a null privateKey, and an empty certificate chain without throwing any exceptions or warnings.

@@ -145,6 +146,22 @@ public CryptoUtil(@NonNull Context context, @NonNull Storage storage, @NonNull S
}
}

private KeyStore.PrivateKeyEntry getKeyEntryCompat(KeyStore keyStore)
throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please refactor this to look more like the project's code-style. Read the in-line comments I left you:

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
   return (KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS, null);
}

//Following code is for API 28+
PrivateKey privateKey = (PrivateKey) keyStore.getKey(KEY_ALIAS, null);
if (privateKey == null) {
    //FIXME: See my review comment below
    return (KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS, null); 
}
//I also moved this since it's used only for the "new" call
Certificate certificate = keyStore.getCertificate(KEY_ALIAS);
return new KeyStore.PrivateKeyEntry(privateKey, new Certificate[]{certificate});

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored to match.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
//Following code is for API 28+
PrivateKey privateKey = (PrivateKey) keyStore.getKey(KEY_ALIAS, null);
Certificate certificate = keyStore.getCertificate(KEY_ALIAS);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is only used for the new KeyStore.PrivateKeyEntry(privateKey, new Certificate[]{certificate}); call, we could avoid calling this if the if-case doesn't require it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lbalmaceda Are you referring to the Certificate object? Since the privateKey check was moved before it, now it is only created when needed. Or did you mean I should create it inline as new Certificate[] {keystore.getCertificate(KEY_ALIAS)}?

@lbalmaceda
Copy link
Contributor

lbalmaceda commented Dec 3, 2018

Hi @sebaslogen @TheGamer007 . Do you need further guidance on resolving the last comments I left? Please, don't hesitate asking. I'm planning a release this week and would be nice if I can include this. Thanks!

@shriakhilc
Copy link
Contributor Author

@lbalmaceda sorry, I wasn't able to check this out yet due to work. I'll get started on this tomorrow and update the PR as soon as possible.

@shriakhilc
Copy link
Contributor Author

@lbalmaceda I've made the changes you requested, just confused about that last one.

@cocojoe
Copy link
Member

cocojoe commented Dec 17, 2018

Thank you @TheGamer007, to set review expectations, lbalmaceda is on vacation.

@lbalmaceda lbalmaceda merged commit 3c74ca6 into auth0:master Dec 26, 2018
@lbalmaceda
Copy link
Contributor

@TheGamer007 thanks for sticking up with this!! cheers

@shriakhilc shriakhilc deleted the fix_secure_credentials_android_p branch January 2, 2019 09:21
@MHausBermel
Copy link

@lbalmaceda Any idea as to when an official release will come with these changes?

@lbalmaceda
Copy link
Contributor

@MHausBermel I'll cut a release today with these changes and then start looking into the issues reported (see open issues) around this class.

@lbalmaceda lbalmaceda modified the milestones: v1-Next, 1.15.0 Jan 10, 2019
@MHausBermel
Copy link

@lbalmaceda Thank you very much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants