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 support for TLS1.2 on pre-lollipop devices. #128

Merged
merged 7 commits into from
Nov 16, 2017

Conversation

dj-mal
Copy link
Contributor

@dj-mal dj-mal commented Nov 6, 2017

Fixes #126

@dj-mal dj-mal force-pushed the prelollipop-tls branch 2 times, most recently from 09f4ffd to 6c0a739 Compare November 6, 2017 05:30
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.

Hey! thanks for the contribution. I've left you some comments. I'd prefer the new classes to be package private and I also don't like the use of PowerMock as well. Please, try to refactor the OkHttpTLS12Compat class and it's usage to achieve the same result without static methods. That would help you not requiring PowerMock at all. Cheers

@@ -132,6 +133,12 @@ public void setUserAgent(String userAgent) {
factory.setUserAgent(userAgent);
}

@SuppressWarnings("unused")
public void enableTls12OnPreLollipop() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Rename to enableTLS12OnPreLollipop, try to make it package private.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If this is made package private, the users have no means to enable TLS 1.2 on the client, since they need to call this method explicitly to enable support. Do you want to move this into the constructor?

* @link https://developer.android.com/reference/javax/net/ssl/SSLSocket.html
* @see SSLSocketFactory
*/
public class Tls12SocketFactory extends SSLSocketFactory {
Copy link
Contributor

Choose a reason for hiding this comment

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

Rename to TLS12SocketFactory, try to make it package private

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Renamed and made package private.

@@ -160,6 +161,11 @@ public void setUserAgent(String userAgent) {
factory.setUserAgent(userAgent);
}

@SuppressWarnings("unused")
public void enableTls12OnPreLollipop() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Rename to enableTLS12OnPreLollipop, try to make it package private.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If this is made package private, the users have no means to enable TLS 1.2 on the client, since they need to call this method explicitly to enable support. Do you want to move this into the constructor?


import javax.net.ssl.SSLContext;

public final class OkHttpTls12Compat {
Copy link
Contributor

Choose a reason for hiding this comment

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

Rename to OkHttpTLS12Compat, try to make it package private.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can't make this package private because both AutehnticationAPIClient and UsersAPIClient use it, and they're in different package.

* @see Tls12SocketFactory
* @param client OkHttpClient instance to be modified
*/
public static void enableSupportOnPreLollipop(OkHttpClient client) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Because this method is "transparent" and will do nothing on already valid API versions, let's rename it to enableForClient. Also keep in mind that static methods are difficult to test if you're just using Mockito/Robolectric.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Method renamed.

// Lollipop is included because some Samsung devices face the same problem on API 21.
return;
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
Log.w(TAG, "TLS 1.2 not supported on API < 16");
Copy link
Contributor

Choose a reason for hiding this comment

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

The whole IF condition can be simplified to:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1)

I don't find useful the log.w line.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the log line and simplified the if condition.

}

@Test
public void shouldConfigTlsOnOrPreApi21() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I know the class already has it, but add an explicit @Config(sdk=21) line here too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added config annotation.


@Test
@Config(sdk=22)
public void shouldNotConfigTlsPostApi21() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Because the min API for this library is 15 and that's excluded from the TLS logic, please add a test for that one as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried but Robolectric doesn't support API level 15 so we can't just add that like other supported APIs.

@dj-mal
Copy link
Contributor Author

dj-mal commented Nov 9, 2017

Thanks for reviewing! I've made the changes accordingly. Most of the comments are reflected in the updated code, although some isn't implemented with reasons explained in individual comments.

I tried making OkHttpTLS12Compat non static, but the outcome may be a bit clumsy in my opinion. I've made a new branch with that, you can check the changes over there:
https://github.com/dj-mal/Auth0.Android/compare/prelollipop-tls...dj-mal:prelollipop-tls-non-static?expand=1

If you think that's OK I can merge the changes into this branch / PR.
Cheers.

@lbalmaceda
Copy link
Contributor

I thought about this and actually, it makes sense to have the TLS flag inside the Auth0 class, like we do for the logging and the OIDC flag. Based on the non-static branch, these are the changes I'd make:

  • Rename OkHttpTLS12Compat to OkHttpClientFactory, which has a single method "createClient(boolean loggingEnabled, boolean tls12Enforced)". Both values are obtained from the Auth0 instance.
  • Change the non-public constructors of the API Clients that receive an OkHttpClient instance to just receive the factory instance. These constructors exist for test purposes only.
  • Factory won't be stored in any variable/field on the API Clients... Use it to create and assign the client on the constructor, but don't assign the factory anywhere (let gc do it's thing).
  • Helper methods inside the Factory will be private. (or package-private if you need to test them).
  • The class will be public and stored inside com.auth0.android/request/internal. Can't think of a better place now.. it must be public because both clients are in separate packages.. so keeping it inside the "internal" package will make people aware that we can break them at any time, and that they should not use it directly. That can be clarified in the class javadoc as well..
  • Remove flag setters/getters from the API Client. Move them to Auth0. Test them.

Please share your thoughts. I think it's cleaner this way.. Ideally we should hide any helper method/class from the users (or keep them in "internal") and try not to put external dependencies on the methods signatures.

  * Create and modify OkHttpClient instance in the factory.
  * Get / set preference on enforcing TLS 1.2 in Auth0.
  * Remove compat logic in API clients.
  * Test TLS / logging in factory instead of API clients.
@dj-mal
Copy link
Contributor Author

dj-mal commented Nov 13, 2017

All are good suggestions and can reduce duplication across the API clients. They're implemented accordingly.

However, since OkHttpClientFactory.createClient uses only parameters from Auth0, maybe an Auth0 instance could be passed (i.e., createClient(auth0)) instead of separate booleans (i.e., createClient(loggingEnabled, tlsEnforced))?

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.

Regarding your last comment, I prefer you don't so we avoid coupling it to another class. The class is already in "internal" so it won't matter a lot the amount of parameters we choose. 👍 I left you the final comments, looks much clearer now thanks 🙂 .

@@ -14,32 +17,49 @@

import javax.net.ssl.SSLContext;

public class OkHttpTLS12Compat {
public class OkHttpClientFactory {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add an additional javadoc at the class level:

Factory class used to configure and obtain a new OkHttpClient instance. This class is meant for internal use only, breaking changes may appear at any time without backwards compatibility guarantee.

or something like that 🙂

}

/**
* Enable TLS 1.2 on the OkHttpClient on API 16-21, which is supported but not enabled by default.
* @link https://github.com/square/okhttp/issues/2372
* @see TLS12SocketFactory
*/
public OkHttpTLS12Compat enableForClient() {
private void enforceTls12(OkHttpClient client) {
// No need to modify client as TLS 1.2 is enabled by default on API21+
// Lollipop is included because some Samsung devices face the same problem on API 21.
if (client == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove client==null check as the client is always valid, since the only entry point is the createClient method. Add a @NonNull annotation to these methods parameters if you want instead, just to help devs as users won't see them.

verifyTLS12NotEnforced(client);
}

private static List generateMockList(OkHttpClient client) {
Copy link
Contributor

Choose a reason for hiding this comment

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

rename generateInterceptorsMockList

@dj-mal
Copy link
Contributor Author

dj-mal commented Nov 14, 2017

Updated according to the comments. Cheers 😃

@lbalmaceda lbalmaceda added this to the v1-Next milestone Nov 14, 2017
@lbalmaceda lbalmaceda merged commit ba14cc5 into auth0:master Nov 16, 2017
@lbalmaceda lbalmaceda modified the milestones: v1-Next, 1.12.0 Nov 16, 2017
@dj-mal dj-mal deleted the prelollipop-tls branch November 17, 2017 01:20
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.

None yet

2 participants