-
Notifications
You must be signed in to change notification settings - Fork 126
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
Implement Thread Safe Credential Manager #542
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.
Looks like it's doing the right things but needs a review from a more Kotlin/Android person as well. Reviewed the non-Code content though and left some comments 👍🏻
auth0/src/main/java/com/auth0/android/authentication/storage/SecureCredentialsManager.kt
Outdated
Show resolved
Hide resolved
auth0/src/main/java/com/auth0/android/authentication/storage/SecureCredentialsManager.kt
Show resolved
Hide resolved
auth0/src/main/java/com/auth0/android/authentication/storage/SecureCredentialsManager.kt
Show resolved
Hide resolved
…ecureCredentialsManager.kt Co-authored-by: Steve Hobbs <steve.hobbs@auth0.com>
lgtm (from what I can understand about
Can you not create a test like this one on Android? |
@adamjmcgrath I checked to solve this for some time and looks like there is not a straightforward way currently to unit test a multi-threaded code in JUnit. Although I have used Reflections (metadata information) to unit test if the |
@lbalmaceda One thing I would like to bring to notice is the addition of a new |
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.
@poovamraj I see with these changes now the developer is required to pass the executor instance. I wonder if customizing that instance the "most typical use case" or if this can be set internally and so avoid having to change the constructor signatures.
*/ | ||
public abstract class BaseCredentialsManager internal constructor( | ||
protected val authenticationClient: AuthenticationAPIClient, | ||
protected val storage: Storage, | ||
private val jwtDecoder: JWTDecoder | ||
private val jwtDecoder: JWTDecoder, | ||
protected val serialExecutor: Executor |
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.
Perhaps this breaking change can be avoided if a new/secondary constructor is defined instead keeping the old signature. For that, you'd need to have a "default executor" instance to use when one is not set by the dev.
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 Instead of making it a secondary constructor I have implemented it as a setter similar to _clock member. This way the user can modify it for testing purposes.
* [SecureCredentialsManager] are executed synchronously to avoid racing conditions. Current usage | ||
* is only around the [getCredentials] method but it can be used in future for others. | ||
*/ | ||
public fun setExecutor(executor: Executor) { |
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 comments on this. This base abstract class is supposed to work as an interface for implementations to follow. I wouldn't add mentions to those implementations in the javadoc, as this base class "doesn't know them".
I noticed that this class is keeping the executor instance but doesn't use it at all -- It only allows to set or get the instance. To me, seems like this instance belongs somewhere else. Perhaps on the classes that implement this one, even if that's repeating that small setter piece of code (because the getter will not be required).
Also, if this is meant to be used by devs for testing purposes only, why not make this function use the "internal" modifier instead? Less chances that someone would override it on production by mistake.
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.
Hey @lbalmaceda, I agree with you on this and exposed the executor through an internal constructor and made it private.
Changes
Please describe both what is changing and why this is important. Include:
Executor
to BaseCredentialsManagerExecutorService
getCredentials
methods are run over this executorsaveCredentials
method in SecureCredentialsManager is made@Synchronized
to avoid race conditionsReferences
#540, #330, #359
Testing
The existing Unit Tests are provided with proper mocks and fixed to accommodate current changes. Apart from that, manual testing is done where multiple threads try to access the above methods with RTR enabled