-
Notifications
You must be signed in to change notification settings - Fork 141
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
Add Android P support for SecureCredentialsManager #203
Conversation
There was a problem hiding this 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) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
Looping you in @sebaslogen since you originally reported the issue. Would you mind testing this PR out and giving us feedback? Thanks |
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. |
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 |
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 . 🕐 |
There was a problem hiding this 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); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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});
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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)}
?
Hi |
@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. |
@lbalmaceda I've made the changes you requested, just confused about that last one. |
Thank you @TheGamer007, to set review expectations, lbalmaceda is on vacation. |
@TheGamer007 thanks for sticking up with this!! cheers |
@lbalmaceda Any idea as to when an official release will come with these changes? |
@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 Thank you very much! |
Fixes #187
Please don't merge while WIP. Only writing proper tests is remaining.