From 314908017c500275d587b174a50a9a3d67c3deb8 Mon Sep 17 00:00:00 2001 From: Luciano Balmaceda Date: Thu, 2 Mar 2017 11:31:14 -0300 Subject: [PATCH 1/9] use buildtools version 25.0.2 --- .travis.yml | 2 +- auth0/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9f80cffbe..b60dc129a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ jdk: android: components: - tools - - build-tools-25.0.1 + - build-tools-25.0.2 - android-25 - extra-google-google_play_services - extra-google-m2repository diff --git a/auth0/build.gradle b/auth0/build.gradle index a68f5d154..152195589 100644 --- a/auth0/build.gradle +++ b/auth0/build.gradle @@ -46,7 +46,7 @@ oss { android { compileSdkVersion 25 - buildToolsVersion '25.0.1' + buildToolsVersion '25.0.2' defaultConfig { minSdkVersion 15 From 8c30d885ec8fc69992137133a546a41d24fc988b Mon Sep 17 00:00:00 2001 From: Luciano Balmaceda Date: Fri, 3 Mar 2017 17:02:28 -0300 Subject: [PATCH 2/9] add circle.yml file --- circle.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 circle.yml diff --git a/circle.yml b/circle.yml new file mode 100644 index 000000000..97aa535e6 --- /dev/null +++ b/circle.yml @@ -0,0 +1,32 @@ +# +# Build configuration for Circle CI +# + +machine: + environment: + ANDROID_HOME: /usr/local/android-sdk-linux + GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"' + _JAVA_OPTIONS: "-Xms512m -Xmx1024m" + ANDROID_API_LEVEL: 25 + ANDROID_BUILD_TOOLS_VERSION: 25.0.2 + java: + version: oraclejdk8 + +dependencies: + cache_directories: + - ~/.gradle + - ~/.android + pre: + - if [ ! -d "/usr/local/android-sdk-linux/tools" ]; then echo y | android update sdk --no-ui --all --filter "tools"; fi + - if [ ! -d "/usr/local/android-sdk-linux/platforms/android-$ANDROID_API_LEVEL" ]; then echo y | android update sdk --no-ui --all --filter "android-$ANDROID_API_LEVEL"; fi + - if [ ! -d "/usr/local/android-sdk-linux/build-tools/$ANDROID_BUILD_TOOLS_VERSION" ]; then echo y | android update sdk --no-ui --all --filter "build-tools-$ANDROID_BUILD_TOOLS_VERSION"; fi + - if [ ! -d "/usr/local/android-sdk-linux/add-ons/addon-google_apis-google-$ANDROID_API_LEVEL" ]; then echo y | android update sdk --no-ui --all --filter "addon-google_apis-google-$ANDROID_API_LEVEL"; fi + - if [ ! -d "/usr/local/android-sdk-linux/extras/google/m2repository" ]; then echo y | android update sdk --no-ui --all --filter "extra-google-m2repository"; fi + - if [ ! -d "/usr/local/android-sdk-linux/extras/google/google_play_services" ]; then echo y | android update sdk --no-ui --all --filter "extra-google-google_play_services"; fi + - if [ ! -d "/usr/local/android-sdk-linux/extras/android/m2repository" ]; then echo y | android update sdk --no-ui --all --filter "extra-android-m2repository"; fi + +test: + override: + - ./gradlew clean test jacocoTestReport --continue --console=plain + post: + - bash <(curl -s https://codecov.io/bash) From 9ae92fc0b255bb3021ffce611f749b39dffeff9e Mon Sep 17 00:00:00 2001 From: Luciano Balmaceda Date: Tue, 14 Mar 2017 13:49:37 -0300 Subject: [PATCH 3/9] add circle-ci badge --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6a09728d8..36fdde866 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # Auth0.Android -[![CI Status](http://img.shields.io/travis/auth0/Auth0.Android.svg?style=flat-square)](https://travis-ci.org/auth0/Auth0.Android) +[![CircleCI](https://img.shields.io/circleci/project/github/auth0/Auth0.Android.svg?style=flat-square)](https://circleci.com/gh/auth0/Auth0.Android/tree/master) +[![TravisCI](http://img.shields.io/travis/auth0/Auth0.Android.svg?style=flat-square)](https://travis-ci.org/auth0/Auth0.Android) [![Coverage Status](https://img.shields.io/codecov/c/github/auth0/Auth0.Android/master.svg?style=flat-square)](https://codecov.io/github/auth0/Auth0.Android) [![License](http://img.shields.io/:license-mit-blue.svg?style=flat)](http://doge.mit-license.org) [![Maven Central](https://img.shields.io/maven-central/v/com.auth0.android/auth0.svg)](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.auth0.android%22%20AND%20a%3A%22auth0%22) -[![Bintray](https://api.bintray.com/packages/auth0/lock-android/Auth0.Android/images/download.svg) ](https://bintray.com/auth0/lock-android/Auth0.Android/_latestVersion) - +[![Bintray](https://api.bintray.com/packages/auth0/android/auth0/images/download.svg)](https://bintray.com/auth0/android/auth0/_latestVersion) Android java toolkit for Auth0 API From 9dd192de335fa3725f051d2ebd37fd47e5bd9b14 Mon Sep 17 00:00:00 2001 From: Luciano Balmaceda Date: Wed, 15 Mar 2017 12:37:39 -0300 Subject: [PATCH 4/9] tune up a bit the circle-ci script --- circle.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/circle.yml b/circle.yml index 97aa535e6..387d3aa29 100644 --- a/circle.yml +++ b/circle.yml @@ -16,14 +16,16 @@ dependencies: cache_directories: - ~/.gradle - ~/.android + - /usr/local/android-sdk-linux/extras + pre: - - if [ ! -d "/usr/local/android-sdk-linux/tools" ]; then echo y | android update sdk --no-ui --all --filter "tools"; fi - - if [ ! -d "/usr/local/android-sdk-linux/platforms/android-$ANDROID_API_LEVEL" ]; then echo y | android update sdk --no-ui --all --filter "android-$ANDROID_API_LEVEL"; fi - - if [ ! -d "/usr/local/android-sdk-linux/build-tools/$ANDROID_BUILD_TOOLS_VERSION" ]; then echo y | android update sdk --no-ui --all --filter "build-tools-$ANDROID_BUILD_TOOLS_VERSION"; fi - - if [ ! -d "/usr/local/android-sdk-linux/add-ons/addon-google_apis-google-$ANDROID_API_LEVEL" ]; then echo y | android update sdk --no-ui --all --filter "addon-google_apis-google-$ANDROID_API_LEVEL"; fi - - if [ ! -d "/usr/local/android-sdk-linux/extras/google/m2repository" ]; then echo y | android update sdk --no-ui --all --filter "extra-google-m2repository"; fi - - if [ ! -d "/usr/local/android-sdk-linux/extras/google/google_play_services" ]; then echo y | android update sdk --no-ui --all --filter "extra-google-google_play_services"; fi - - if [ ! -d "/usr/local/android-sdk-linux/extras/android/m2repository" ]; then echo y | android update sdk --no-ui --all --filter "extra-android-m2repository"; fi + - if [ ! -d "$ANDROID_HOME/tools" ]; then echo y | android update sdk --no-ui --all --filter "tools"; fi + - if [ ! -d "$ANDROID_HOME/platforms/android-$ANDROID_API_LEVEL" ]; then echo y | android update sdk --no-ui --all --filter "android-$ANDROID_API_LEVEL"; fi + - if [ ! -d "$ANDROID_HOME/build-tools/$ANDROID_BUILD_TOOLS_VERSION" ]; then echo y | android update sdk --no-ui --all --filter "build-tools-$ANDROID_BUILD_TOOLS_VERSION"; fi + - if [ ! -d "$ANDROID_HOME/add-ons/addon-google_apis-google-$ANDROID_API_LEVEL" ]; then echo y | android update sdk --no-ui --all --filter "addon-google_apis-google-$ANDROID_API_LEVEL"; fi + - echo y | android update sdk --no-ui --all --filter "extra-google-m2repository" + - echo y | android update sdk --no-ui --all --filter "extra-google-google_play_services" + - echo y | android update sdk --no-ui --all --filter "extra-android-m2repository" test: override: From d7a8c4e800615ee649a784983dde9c5c85e58ad9 Mon Sep 17 00:00:00 2001 From: Luciano Balmaceda Date: Wed, 15 Mar 2017 15:20:54 -0300 Subject: [PATCH 5/9] remove travis CI --- .travis.yml | 27 --------------------------- README.md | 1 - 2 files changed, 28 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b60dc129a..000000000 --- a/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -language: android -sudo: false -jdk: - - oraclejdk8 -android: - components: - - tools - - build-tools-25.0.2 - - android-25 - - extra-google-google_play_services - - extra-google-m2repository - - extra-android-m2repository - - addon-google_apis-google-25 -before_cache: - - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock - - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ -cache: - directories: - - $HOME/.gradle/caches/ - - $HOME/.gradle/wrapper/ -script: - - "./gradlew clean test jacocoTestReport --continue" -after_success: - - bash <(curl -s https://codecov.io/bash) -branches: - only: - - master \ No newline at end of file diff --git a/README.md b/README.md index 36fdde866..52e99f349 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # Auth0.Android [![CircleCI](https://img.shields.io/circleci/project/github/auth0/Auth0.Android.svg?style=flat-square)](https://circleci.com/gh/auth0/Auth0.Android/tree/master) -[![TravisCI](http://img.shields.io/travis/auth0/Auth0.Android.svg?style=flat-square)](https://travis-ci.org/auth0/Auth0.Android) [![Coverage Status](https://img.shields.io/codecov/c/github/auth0/Auth0.Android/master.svg?style=flat-square)](https://codecov.io/github/auth0/Auth0.Android) [![License](http://img.shields.io/:license-mit-blue.svg?style=flat)](http://doge.mit-license.org) [![Maven Central](https://img.shields.io/maven-central/v/com.auth0.android/auth0.svg)](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.auth0.android%22%20AND%20a%3A%22auth0%22) From 4da96709acef8b36805a63c581f4e370a42bc1ea Mon Sep 17 00:00:00 2001 From: Luciano Balmaceda Date: Tue, 4 Apr 2017 15:49:07 -0300 Subject: [PATCH 6/9] fix custom rule error message parsing for WebAuthProvider --- .../auth0/android/provider/OAuthManager.java | 8 +- .../android/provider/WebAuthProviderTest.java | 86 ++++++++++++++----- 2 files changed, 69 insertions(+), 25 deletions(-) diff --git a/auth0/src/main/java/com/auth0/android/provider/OAuthManager.java b/auth0/src/main/java/com/auth0/android/provider/OAuthManager.java index eb57239d6..38fbb83af 100644 --- a/auth0/src/main/java/com/auth0/android/provider/OAuthManager.java +++ b/auth0/src/main/java/com/auth0/android/provider/OAuthManager.java @@ -34,6 +34,7 @@ class OAuthManager { static final String RESPONSE_TYPE_CODE = "code"; private static final String ERROR_VALUE_ACCESS_DENIED = "access_denied"; + private static final String ERROR_VALUE_UNAUTHORIZED = "unauthorized"; private static final String METHOD_SHA_256 = "S256"; private static final String KEY_CODE_CHALLENGE = "code_challenge"; private static final String KEY_CODE_CHALLENGE_METHOD = "code_challenge_method"; @@ -41,6 +42,7 @@ class OAuthManager { private static final String KEY_REDIRECT_URI = "redirect_uri"; private static final String KEY_TELEMETRY = "auth0Client"; private static final String KEY_ERROR = "error"; + private static final String KEY_ERROR_DESCRIPTION = "error_description"; private static final String KEY_ID_TOKEN = "id_token"; private static final String KEY_ACCESS_TOKEN = "access_token"; private static final String KEY_TOKEN_TYPE = "token_type"; @@ -113,7 +115,7 @@ public boolean resumeAuthorization(AuthorizeResult data) { logDebug("The parsed CallbackURI contains the following values: " + values); try { - assertNoError(values.get(KEY_ERROR)); + assertNoError(values.get(KEY_ERROR), values.get(KEY_ERROR_DESCRIPTION)); assertValidState(parameters.get(KEY_STATE), values.get(KEY_STATE)); if (parameters.get(KEY_RESPONSE_TYPE).contains(RESPONSE_TYPE_ID_TOKEN)) { assertValidNonce(parameters.get(KEY_NONCE), values.get(KEY_ID_TOKEN)); @@ -154,13 +156,15 @@ public void onSuccess(@NonNull Credentials codeCredentials) { //Helper Methods - private void assertNoError(String errorValue) throws AuthenticationException { + private void assertNoError(String errorValue, String errorDescription) throws AuthenticationException { if (errorValue == null) { return; } Log.e(TAG, "Error, access denied. Check that the required Permissions are granted and that the Application has this Connection configured in Auth0 Dashboard."); if (ERROR_VALUE_ACCESS_DENIED.equalsIgnoreCase(errorValue)) { throw new AuthenticationException(ERROR_VALUE_ACCESS_DENIED, "Permissions were not granted. Try again."); + } else if (ERROR_VALUE_UNAUTHORIZED.equalsIgnoreCase(errorValue)) { + throw new AuthenticationException(ERROR_VALUE_UNAUTHORIZED, errorDescription); } else { throw new AuthenticationException("a0.invalid_configuration", "The application isn't configured properly for the social connection. Please check your Auth0's application configuration"); } diff --git a/auth0/src/test/java/com/auth0/android/provider/WebAuthProviderTest.java b/auth0/src/test/java/com/auth0/android/provider/WebAuthProviderTest.java index afd88eb1c..e66120754 100644 --- a/auth0/src/test/java/com/auth0/android/provider/WebAuthProviderTest.java +++ b/auth0/src/test/java/com/auth0/android/provider/WebAuthProviderTest.java @@ -1045,7 +1045,7 @@ public void shouldResumeWithRequestCodeWithResponseTypeIdToken() throws Exceptio String sentNonce = uri.getQueryParameter(KEY_NONCE); assertThat(sentState, is(not(isEmptyOrNullString()))); assertThat(sentNonce, is(not(isEmptyOrNullString()))); - Intent intent = createAuthIntent(createHash(customNonceJWT(sentNonce), null, null, null, sentState, null)); + Intent intent = createAuthIntent(createHash(customNonceJWT(sentNonce), null, null, null, sentState, null, null)); assertTrue(WebAuthProvider.resume(REQUEST_CODE, Activity.RESULT_OK, intent)); verify(callback).onSuccess(any(Credentials.class)); @@ -1065,7 +1065,7 @@ public void shouldResumeWithIntentWithResponseTypeIdToken() throws Exception { String sentNonce = uri.getQueryParameter(KEY_NONCE); assertThat(sentState, is(not(isEmptyOrNullString()))); assertThat(sentNonce, is(not(isEmptyOrNullString()))); - Intent intent = createAuthIntent(createHash(customNonceJWT(sentNonce), null, null, null, sentState, null)); + Intent intent = createAuthIntent(createHash(customNonceJWT(sentNonce), null, null, null, sentState, null, null)); assertTrue(WebAuthProvider.resume(intent)); verify(callback).onSuccess(any(Credentials.class)); @@ -1088,7 +1088,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable { .useCodeGrant(true) .withPKCE(pkce) .start(activity, callback); - Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null)); + Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null, null)); int DEFAULT_REQUEST_CODE = 110; assertTrue(WebAuthProvider.resume(DEFAULT_REQUEST_CODE, Activity.RESULT_OK, intent)); } @@ -1116,7 +1116,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable { String sentState = uri.getQueryParameter(KEY_STATE); assertThat(sentState, is(not(isEmptyOrNullString()))); - Intent intent = createAuthIntent(createHash("urlId", "urlAccess", "urlRefresh", "urlType", sentState, null)); + Intent intent = createAuthIntent(createHash("urlId", "urlAccess", "urlRefresh", "urlType", sentState, null, null)); assertTrue(WebAuthProvider.resume(intent)); ArgumentCaptor credentialsCaptor = ArgumentCaptor.forClass(Credentials.class); @@ -1153,7 +1153,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable { String sentState = uri.getQueryParameter(KEY_STATE); assertThat(sentState, is(not(isEmptyOrNullString()))); - Intent intent = createAuthIntent(createHash("urlId", "urlAccess", "urlRefresh", "urlType", sentState, null)); + Intent intent = createAuthIntent(createHash("urlId", "urlAccess", "urlRefresh", "urlType", sentState, null, null)); assertTrue(WebAuthProvider.resume(REQUEST_CODE, Activity.RESULT_OK, intent)); ArgumentCaptor credentialsCaptor = ArgumentCaptor.forClass(Credentials.class); @@ -1180,7 +1180,7 @@ public void shouldResumeWithIntentWithImplicitGrant() throws Exception { String sentState = uri.getQueryParameter(KEY_STATE); assertThat(sentState, is(not(isEmptyOrNullString()))); - Intent intent = createAuthIntent(createHash("urlId", "urlAccess", "urlRefresh", "urlType", sentState, null)); + Intent intent = createAuthIntent(createHash("urlId", "urlAccess", "urlRefresh", "urlType", sentState, null, null)); assertTrue(WebAuthProvider.resume(intent)); verify(callback).onSuccess(any(Credentials.class)); @@ -1199,7 +1199,7 @@ public void shouldResumeWithRequestCodeWithImplicitGrant() throws Exception { String sentState = uri.getQueryParameter(KEY_STATE); assertThat(sentState, is(not(isEmptyOrNullString()))); - Intent intent = createAuthIntent(createHash("urlId", "urlAccess", "urlRefresh", "urlType", sentState, null)); + Intent intent = createAuthIntent(createHash("urlId", "urlAccess", "urlRefresh", "urlType", sentState, null, null)); assertTrue(WebAuthProvider.resume(REQUEST_CODE, Activity.RESULT_OK, intent)); verify(callback).onSuccess(any(Credentials.class)); @@ -1222,7 +1222,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable { .useCodeGrant(true) .withPKCE(pkce) .start(activity, callback); - Intent intent = createAuthIntent(createHash("urlId", "urlAccess", "urlRefresh", "urlType", "1234567890", null)); + Intent intent = createAuthIntent(createHash("urlId", "urlAccess", "urlRefresh", "urlType", "1234567890", null, null)); assertTrue(WebAuthProvider.resume(intent)); verify(callback).onFailure(dialog); @@ -1245,7 +1245,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable { .useCodeGrant(true) .withPKCE(pkce) .start(activity, callback); - Intent intent = createAuthIntent(createHash("urlId", "urlAccess", "urlRefresh", "urlType", "1234567890", null)); + Intent intent = createAuthIntent(createHash("urlId", "urlAccess", "urlRefresh", "urlType", "1234567890", null, null)); assertTrue(WebAuthProvider.resume(intent)); verify(callback).onFailure(exception); @@ -1258,7 +1258,7 @@ public void shouldFailToResumeWithIntentWithAccessDenied() throws Exception { .withState("1234567890") .useCodeGrant(false) .start(activity, callback); - Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", "access_denied")); + Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", "access_denied", null)); assertTrue(WebAuthProvider.resume(intent)); verify(callback).onFailure(authExceptionCaptor.capture()); @@ -1275,7 +1275,7 @@ public void shouldFailToResumeWithRequestCodeWithAccessDenied() throws Exception .withState("1234567890") .useCodeGrant(false) .start(activity, callback, REQUEST_CODE); - Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", "access_denied")); + Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", "access_denied", null)); assertTrue(WebAuthProvider.resume(REQUEST_CODE, Activity.RESULT_OK, intent)); verify(callback).onFailure(authExceptionCaptor.capture()); @@ -1285,6 +1285,40 @@ public void shouldFailToResumeWithRequestCodeWithAccessDenied() throws Exception assertThat(authExceptionCaptor.getValue().getDescription(), is("Permissions were not granted. Try again.")); } + @SuppressWarnings({"deprecation", "ThrowableResultOfMethodCallIgnored"}) + @Test + public void shouldFailToResumeWithIntentWithRuleError() throws Exception { + WebAuthProvider.init(account) + .withState("1234567890") + .useCodeGrant(false) + .start(activity, callback); + Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", "unauthorized", "Custom Rule Error")); + assertTrue(WebAuthProvider.resume(intent)); + + verify(callback).onFailure(authExceptionCaptor.capture()); + + assertThat(authExceptionCaptor.getValue(), is(notNullValue())); + assertThat(authExceptionCaptor.getValue().getCode(), is("unauthorized")); + assertThat(authExceptionCaptor.getValue().getDescription(), is("Custom Rule Error")); + } + + @SuppressWarnings({"deprecation", "ThrowableResultOfMethodCallIgnored"}) + @Test + public void shouldFailToResumeWithRequestCodeWithRuleError() throws Exception { + WebAuthProvider.init(account) + .withState("1234567890") + .useCodeGrant(false) + .start(activity, callback, REQUEST_CODE); + Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", "unauthorized", "Custom Rule Error")); + assertTrue(WebAuthProvider.resume(REQUEST_CODE, Activity.RESULT_OK, intent)); + + verify(callback).onFailure(authExceptionCaptor.capture()); + + assertThat(authExceptionCaptor.getValue(), is(notNullValue())); + assertThat(authExceptionCaptor.getValue().getCode(), is("unauthorized")); + assertThat(authExceptionCaptor.getValue().getDescription(), is("Custom Rule Error")); + } + @SuppressWarnings({"deprecation", "ThrowableResultOfMethodCallIgnored"}) @Test public void shouldFailToResumeWithIntentWithConfigurationInvalid() throws Exception { @@ -1292,7 +1326,7 @@ public void shouldFailToResumeWithIntentWithConfigurationInvalid() throws Except .withState("1234567890") .useCodeGrant(false) .start(activity, callback); - Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", "some other error")); + Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", "some other error", null)); assertTrue(WebAuthProvider.resume(intent)); verify(callback).onFailure(authExceptionCaptor.capture()); @@ -1309,7 +1343,7 @@ public void shouldFailToResumeWithRequestCodeWithConfigurationInvalid() throws E .withState("1234567890") .useCodeGrant(false) .start(activity, callback, REQUEST_CODE); - Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", "some other error")); + Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", "some other error", null)); assertTrue(WebAuthProvider.resume(REQUEST_CODE, Activity.RESULT_OK, intent)); verify(callback).onFailure(authExceptionCaptor.capture()); @@ -1326,7 +1360,7 @@ public void shouldFailToResumeWithIntentWithInvalidState() throws Exception { .withState("abcdefghijk") .useCodeGrant(false) .start(activity, callback); - Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null)); + Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null, null)); assertTrue(WebAuthProvider.resume(intent)); verify(callback).onFailure(authExceptionCaptor.capture()); @@ -1343,7 +1377,7 @@ public void shouldFailToResumeWithRequestCodeWithInvalidState() throws Exception .withState("abcdefghijk") .useCodeGrant(false) .start(activity, callback, REQUEST_CODE); - Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null)); + Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null, null)); assertTrue(WebAuthProvider.resume(REQUEST_CODE, Activity.RESULT_OK, intent)); verify(callback).onFailure(authExceptionCaptor.capture()); @@ -1361,7 +1395,7 @@ public void shouldFailToResumeWithIntentWithInvalidNonce() throws Exception { .withNonce("0987654321") .withResponseType(ResponseType.ID_TOKEN) .start(activity, callback); - Intent intent = createAuthIntent(createHash("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJub25jZSI6IjEyMzQ1Njc4OTAifQ.oUb6xFIEPJQrFbel_Js4SaOwpFfM_kxHxI7xDOHgghk", null, null, null, "state", null)); + Intent intent = createAuthIntent(createHash("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJub25jZSI6IjEyMzQ1Njc4OTAifQ.oUb6xFIEPJQrFbel_Js4SaOwpFfM_kxHxI7xDOHgghk", null, null, null, "state", null, null)); assertTrue(WebAuthProvider.resume(intent)); verify(callback).onFailure(authExceptionCaptor.capture()); @@ -1379,7 +1413,7 @@ public void shouldFailToResumeWithRequestCodeWithInvalidNonce() throws Exception .withNonce("0987654321") .withResponseType(ResponseType.ID_TOKEN) .start(activity, callback, REQUEST_CODE); - Intent intent = createAuthIntent(createHash("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJub25jZSI6IjEyMzQ1Njc4OTAifQ.oUb6xFIEPJQrFbel_Js4SaOwpFfM_kxHxI7xDOHgghk", null, null, null, "state", null)); + Intent intent = createAuthIntent(createHash("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJub25jZSI6IjEyMzQ1Njc4OTAifQ.oUb6xFIEPJQrFbel_Js4SaOwpFfM_kxHxI7xDOHgghk", null, null, null, "state", null, null)); assertTrue(WebAuthProvider.resume(REQUEST_CODE, Activity.RESULT_OK, intent)); verify(callback).onFailure(authExceptionCaptor.capture()); @@ -1397,7 +1431,7 @@ public void shouldFailToResumeWithUnexpectedRequestCode() throws Exception { .useCodeGrant(false) .start(activity, callback); - Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null)); + Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null, null)); assertFalse(WebAuthProvider.resume(999, Activity.RESULT_OK, intent)); } @@ -1409,7 +1443,7 @@ public void shouldFailToResumeWithResultCancelled() throws Exception { .useCodeGrant(false) .start(activity, callback, REQUEST_CODE); - Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null)); + Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null, null)); assertFalse(WebAuthProvider.resume(REQUEST_CODE, Activity.RESULT_CANCELED, intent)); } @@ -1421,7 +1455,7 @@ public void shouldFailToResumeWithResultNotOK() throws Exception { .useCodeGrant(false) .start(activity, callback, REQUEST_CODE); - Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null)); + Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null, null)); assertFalse(WebAuthProvider.resume(REQUEST_CODE, 999, intent)); } @@ -1490,7 +1524,7 @@ public void shouldClearInstanceAfterSuccessAuthenticationWithIntent() throws Exc .start(activity, callback); assertThat(WebAuthProvider.getInstance(), is(notNullValue())); - Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null)); + Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null, null)); assertTrue(WebAuthProvider.resume(intent)); assertThat(WebAuthProvider.getInstance(), is(nullValue())); } @@ -1502,7 +1536,7 @@ public void shouldClearInstanceAfterSuccessAuthenticationWithRequestCode() throw .start(activity, callback, REQUEST_CODE); assertThat(WebAuthProvider.getInstance(), is(notNullValue())); - Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null)); + Intent intent = createAuthIntent(createHash("iToken", "aToken", null, "refresh_token", "1234567890", null, null)); assertTrue(WebAuthProvider.resume(REQUEST_CODE, Activity.RESULT_OK, intent)); assertThat(WebAuthProvider.getInstance(), is(nullValue())); } @@ -1515,7 +1549,7 @@ private Intent createAuthIntent(String hash) { return intent; } - private String createHash(@Nullable String idToken, @Nullable String accessToken, @Nullable String refreshToken, @Nullable String tokenType, @Nullable String state, @Nullable String error) { + private String createHash(@Nullable String idToken, @Nullable String accessToken, @Nullable String refreshToken, @Nullable String tokenType, @Nullable String state, @Nullable String error, @Nullable String errorDescription) { String hash = "#"; if (accessToken != null) { hash = hash.concat("access_token=" + accessToken); @@ -1550,6 +1584,12 @@ private String createHash(@Nullable String idToken, @Nullable String accessToken } hash = hash.concat("error=" + error); } + if (errorDescription != null) { + if (!hash.endsWith("&")) { + hash = hash.concat("&"); + } + hash = hash.concat("error_description=" + errorDescription); + } return hash.length() == 1 ? "" : hash; } From bced8e5ce48e980adf6aa9390b5f469c8149b51b Mon Sep 17 00:00:00 2001 From: Luciano Balmaceda Date: Wed, 5 Apr 2017 12:51:45 -0300 Subject: [PATCH 7/9] check for null or empty description --- .../AuthenticationException.java | 3 +- .../android/provider/WebAuthProviderTest.java | 49 +++++++++---------- .../AuthenticationErrorBuilderTest.java | 5 ++ 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/auth0/src/main/java/com/auth0/android/authentication/AuthenticationException.java b/auth0/src/main/java/com/auth0/android/authentication/AuthenticationException.java index 4a782ed8b..46c039a47 100644 --- a/auth0/src/main/java/com/auth0/android/authentication/AuthenticationException.java +++ b/auth0/src/main/java/com/auth0/android/authentication/AuthenticationException.java @@ -24,6 +24,7 @@ package com.auth0.android.authentication; +import android.text.TextUtils; import android.util.Log; import com.auth0.android.Auth0Exception; @@ -122,7 +123,7 @@ public int getStatusCode() { * @return the error description. */ public String getDescription() { - if (description != null) { + if (!TextUtils.isEmpty(description)) { return description; } if (UNKNOWN_ERROR.equals(getCode())) { diff --git a/auth0/src/test/java/com/auth0/android/provider/WebAuthProviderTest.java b/auth0/src/test/java/com/auth0/android/provider/WebAuthProviderTest.java index e66120754..cde1d8f73 100644 --- a/auth0/src/test/java/com/auth0/android/provider/WebAuthProviderTest.java +++ b/auth0/src/test/java/com/auth0/android/provider/WebAuthProviderTest.java @@ -1552,43 +1552,42 @@ private Intent createAuthIntent(String hash) { private String createHash(@Nullable String idToken, @Nullable String accessToken, @Nullable String refreshToken, @Nullable String tokenType, @Nullable String state, @Nullable String error, @Nullable String errorDescription) { String hash = "#"; if (accessToken != null) { - hash = hash.concat("access_token=" + accessToken); + hash = hash.concat("access_token=") + .concat(accessToken) + .concat("&"); } if (idToken != null) { - if (!hash.endsWith("&")) { - hash = hash.concat("&"); - } - hash = hash.concat("id_token=" + idToken); + hash = hash.concat("id_token=") + .concat(idToken) + .concat("&"); } if (refreshToken != null) { - if (!hash.endsWith("&")) { - hash = hash.concat("&"); - } - hash = hash.concat("refresh_token=" + refreshToken); + hash = hash.concat("refresh_token=") + .concat(refreshToken) + .concat("&"); } if (tokenType != null) { - if (!hash.endsWith("&")) { - hash = hash.concat("&"); - } - hash = hash.concat("token_type=" + tokenType); + hash = hash.concat("token_type=") + .concat(tokenType) + .concat("&"); } if (state != null) { - if (!hash.endsWith("&")) { - hash = hash.concat("&"); - } - hash = hash.concat("state=" + state); + hash = hash.concat("state=") + .concat(state) + .concat("&"); } if (error != null) { - if (!hash.endsWith("&")) { - hash = hash.concat("&"); - } - hash = hash.concat("error=" + error); + hash = hash.concat("error=") + .concat(error) + .concat("&"); } if (errorDescription != null) { - if (!hash.endsWith("&")) { - hash = hash.concat("&"); - } - hash = hash.concat("error_description=" + errorDescription); + hash = hash.concat("error_description=") + .concat(errorDescription) + .concat("&"); + } + if (hash.endsWith("&")) { + hash = hash.substring(0, hash.length() - 1); } return hash.length() == 1 ? "" : hash; } diff --git a/auth0/src/test/java/com/auth0/android/request/internal/AuthenticationErrorBuilderTest.java b/auth0/src/test/java/com/auth0/android/request/internal/AuthenticationErrorBuilderTest.java index 91b2fd5ee..72b7276a4 100644 --- a/auth0/src/test/java/com/auth0/android/request/internal/AuthenticationErrorBuilderTest.java +++ b/auth0/src/test/java/com/auth0/android/request/internal/AuthenticationErrorBuilderTest.java @@ -6,7 +6,10 @@ import org.hamcrest.CoreMatchers; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.Mockito; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; import java.util.HashMap; import java.util.Map; @@ -16,6 +19,8 @@ import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertThat; +@RunWith(RobolectricTestRunner.class) +@Config(constants = com.auth0.android.auth0.BuildConfig.class, sdk = 21, manifest = Config.NONE) public class AuthenticationErrorBuilderTest { private AuthenticationErrorBuilder builder; From 4335edd8274c67458aeeffe99bc7e982237eaf12 Mon Sep 17 00:00:00 2001 From: Luciano Balmaceda Date: Wed, 5 Apr 2017 16:16:19 -0300 Subject: [PATCH 8/9] add tests to keep the coverage unchanged --- .../android/provider/CallbackHelperTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/auth0/src/test/java/com/auth0/android/provider/CallbackHelperTest.java b/auth0/src/test/java/com/auth0/android/provider/CallbackHelperTest.java index 435e302c9..9b4d8d238 100644 --- a/auth0/src/test/java/com/auth0/android/provider/CallbackHelperTest.java +++ b/auth0/src/test/java/com/auth0/android/provider/CallbackHelperTest.java @@ -165,6 +165,15 @@ public void shouldGetEmptyValuesWhenQueryIsEmpty() throws Exception { assertThat(values, IsMapWithSize.anEmptyMap()); } + @Test + public void shouldGetEmptyValuesWhenQueryBeginsWithAmpersand() throws Exception { + String uriString = "https://my.website.com/some/page?&key_without_value"; + Uri uri = Uri.parse(uriString); + final Map values = CallbackHelper.getValuesFromUri(uri); + assertThat(values, notNullValue()); + assertThat(values, IsMapWithSize.anEmptyMap()); + } + @Test public void shouldGetEmptyValuesWhenFragmentIsEmpty() throws Exception { String uriString = "https://my.website.com/some/page#"; @@ -173,4 +182,13 @@ public void shouldGetEmptyValuesWhenFragmentIsEmpty() throws Exception { assertThat(values, notNullValue()); assertThat(values, IsMapWithSize.anEmptyMap()); } + + @Test + public void shouldGetEmptyValuesWhenFragmentBeginsWithAmpersand() throws Exception { + String uriString = "https://my.website.com/some/page#&key_without_value"; + Uri uri = Uri.parse(uriString); + final Map values = CallbackHelper.getValuesFromUri(uri); + assertThat(values, notNullValue()); + assertThat(values, IsMapWithSize.anEmptyMap()); + } } \ No newline at end of file From 92d5cfad76b9f6fac12e95f572339f32bf49078f Mon Sep 17 00:00:00 2001 From: Luciano Balmaceda Date: Thu, 6 Apr 2017 11:40:08 -0300 Subject: [PATCH 9/9] Release 1.7.0 --- CHANGELOG.md | 6 ++++++ README.md | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38bed51ff..21d3d17ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## [1.7.0](https://github.com/auth0/Auth0.Android/tree/1.7.0) (2017-04-06) +[Full Changelog](https://github.com/auth0/Auth0.Android/compare/1.6.0...1.7.0) + +**Added** +- Add WebAuthProvider Rule error message parsing [\#89](https://github.com/auth0/Auth0.Android/pull/89) ([lbalmaceda](https://github.com/lbalmaceda)) + ## [1.6.0](https://github.com/auth0/Auth0.Android/tree/1.6.0) (2017-03-02) [Full Changelog](https://github.com/auth0/Auth0.Android/compare/1.5.0...1.6.0) diff --git a/README.md b/README.md index 52e99f349..b26939cab 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Auth0.android is available through [Gradle](https://gradle.org/). To install it, ```gradle dependencies { - compile 'com.auth0.android:auth0:1.6.0' + compile 'com.auth0.android:auth0:1.7.0' } ```