diff --git a/auth0/src/main/java/com/auth0/android/authentication/AuthenticationAPIClient.kt b/auth0/src/main/java/com/auth0/android/authentication/AuthenticationAPIClient.kt index c5aa9f1b2..ecac17918 100755 --- a/auth0/src/main/java/com/auth0/android/authentication/AuthenticationAPIClient.kt +++ b/auth0/src/main/java/com/auth0/android/authentication/AuthenticationAPIClient.kt @@ -3,10 +3,12 @@ package com.auth0.android.authentication import androidx.annotation.VisibleForTesting import com.auth0.android.Auth0 import com.auth0.android.Auth0Exception +import com.auth0.android.NetworkErrorException import com.auth0.android.request.* import com.auth0.android.request.internal.* import com.auth0.android.request.internal.GsonAdapter.Companion.forMap import com.auth0.android.request.internal.GsonAdapter.Companion.forMapOf +import com.auth0.android.request.internal.ResponseUtils.isNetworkError import com.auth0.android.result.Challenge import com.auth0.android.result.Credentials import com.auth0.android.result.DatabaseUser @@ -815,6 +817,12 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe } override fun fromException(cause: Throwable): AuthenticationException { + if (isNetworkError(cause)) { + return AuthenticationException( + "Failed to execute the network request", + NetworkErrorException(cause) + ) + } return AuthenticationException( "Something went wrong", Auth0Exception("Something went wrong", cause) diff --git a/auth0/src/main/java/com/auth0/android/authentication/AuthenticationException.kt b/auth0/src/main/java/com/auth0/android/authentication/AuthenticationException.kt index 652204db4..c0ec90419 100644 --- a/auth0/src/main/java/com/auth0/android/authentication/AuthenticationException.kt +++ b/auth0/src/main/java/com/auth0/android/authentication/AuthenticationException.kt @@ -4,10 +4,7 @@ import android.text.TextUtils import android.util.Log import com.auth0.android.Auth0Exception import com.auth0.android.NetworkErrorException -import java.net.SocketTimeoutException -import java.net.UnknownHostException import com.auth0.android.provider.TokenValidationException -import java.net.SocketException public class AuthenticationException : Auth0Exception { private var code: String? = null @@ -107,15 +104,8 @@ public class AuthenticationException : Auth0Exception { } // When the request failed due to network issues - // Currently [NetworkErrorException] is not properly thrown from [createErrorAdapter] in - // [AuthenticationAPIClient] and [UserAPIClient]. This will be fixed in the next major to avoid - // breaking change in the current major. We are not using IOException to check for the error - // since it is too broad. public val isNetworkError: Boolean get() = cause is NetworkErrorException - || cause?.cause is UnknownHostException - || cause?.cause is SocketTimeoutException - || cause?.cause is SocketException // When there is no Browser app installed to handle the web authentication public val isBrowserAppNotAvailable: Boolean diff --git a/auth0/src/main/java/com/auth0/android/authentication/storage/BaseCredentialsManager.kt b/auth0/src/main/java/com/auth0/android/authentication/storage/BaseCredentialsManager.kt index e71af8322..506f4d9c3 100644 --- a/auth0/src/main/java/com/auth0/android/authentication/storage/BaseCredentialsManager.kt +++ b/auth0/src/main/java/com/auth0/android/authentication/storage/BaseCredentialsManager.kt @@ -6,6 +6,7 @@ import com.auth0.android.callback.Callback import com.auth0.android.result.Credentials import com.auth0.android.util.Clock import java.util.* + /** * Base class meant to abstract common logic across Credentials Manager implementations. * The scope of this class is package-private, as it's not meant to be exposed @@ -35,6 +36,65 @@ public abstract class BaseCredentialsManager internal constructor( callback: Callback ) + public abstract fun getCredentials( + scope: String?, + minTtl: Int, + parameters: Map, + callback: Callback + ) + + public abstract fun getCredentials( + scope: String?, + minTtl: Int, + parameters: Map, + forceRefresh: Boolean, + callback: Callback + ) + + public abstract fun getCredentials( + scope: String?, + minTtl: Int, + parameters: Map, + headers: Map, + forceRefresh: Boolean, + callback: Callback + ) + + @JvmSynthetic + @Throws(CredentialsManagerException::class) + public abstract suspend fun awaitCredentials(): Credentials + + @JvmSynthetic + @Throws(CredentialsManagerException::class) + public abstract suspend fun awaitCredentials(scope: String?, minTtl: Int): Credentials + + @JvmSynthetic + @Throws(CredentialsManagerException::class) + public abstract suspend fun awaitCredentials( + scope: String?, + minTtl: Int, + parameters: Map + ): Credentials + + @JvmSynthetic + @Throws(CredentialsManagerException::class) + public abstract suspend fun awaitCredentials( + scope: String?, + minTtl: Int, + parameters: Map, + forceRefresh: Boolean + ): Credentials + + @JvmSynthetic + @Throws(CredentialsManagerException::class) + public abstract suspend fun awaitCredentials( + scope: String?, + minTtl: Int, + parameters: Map, + headers: Map, + forceRefresh: Boolean + ): Credentials + public abstract fun clearCredentials() public abstract fun hasValidCredentials(): Boolean public abstract fun hasValidCredentials(minTtl: Long): Boolean diff --git a/auth0/src/main/java/com/auth0/android/authentication/storage/CredentialsManager.kt b/auth0/src/main/java/com/auth0/android/authentication/storage/CredentialsManager.kt index 7f5a20b6e..9e6af7d9a 100644 --- a/auth0/src/main/java/com/auth0/android/authentication/storage/CredentialsManager.kt +++ b/auth0/src/main/java/com/auth0/android/authentication/storage/CredentialsManager.kt @@ -61,7 +61,7 @@ public class CredentialsManager @VisibleForTesting(otherwise = VisibleForTesting */ @JvmSynthetic @Throws(CredentialsManagerException::class) - public suspend fun awaitCredentials(): Credentials { + override suspend fun awaitCredentials(): Credentials { return awaitCredentials(null, 0) } @@ -76,7 +76,7 @@ public class CredentialsManager @VisibleForTesting(otherwise = VisibleForTesting */ @JvmSynthetic @Throws(CredentialsManagerException::class) - public suspend fun awaitCredentials(scope: String?, minTtl: Int): Credentials { + override suspend fun awaitCredentials(scope: String?, minTtl: Int): Credentials { return awaitCredentials(scope, minTtl, emptyMap()) } @@ -92,7 +92,7 @@ public class CredentialsManager @VisibleForTesting(otherwise = VisibleForTesting */ @JvmSynthetic @Throws(CredentialsManagerException::class) - public suspend fun awaitCredentials( + override suspend fun awaitCredentials( scope: String?, minTtl: Int, parameters: Map @@ -113,7 +113,7 @@ public class CredentialsManager @VisibleForTesting(otherwise = VisibleForTesting */ @JvmSynthetic @Throws(CredentialsManagerException::class) - public suspend fun awaitCredentials( + override suspend fun awaitCredentials( scope: String?, minTtl: Int, parameters: Map, @@ -136,7 +136,7 @@ public class CredentialsManager @VisibleForTesting(otherwise = VisibleForTesting */ @JvmSynthetic @Throws(CredentialsManagerException::class) - public suspend fun awaitCredentials( + override suspend fun awaitCredentials( scope: String?, minTtl: Int, parameters: Map, @@ -200,7 +200,7 @@ public class CredentialsManager @VisibleForTesting(otherwise = VisibleForTesting * @param parameters additional parameters to send in the request to refresh expired credentials * @param callback the callback that will receive a valid [Credentials] or the [CredentialsManagerException]. */ - public fun getCredentials( + override fun getCredentials( scope: String?, minTtl: Int, parameters: Map, @@ -220,7 +220,7 @@ public class CredentialsManager @VisibleForTesting(otherwise = VisibleForTesting * @param forceRefresh this will avoid returning the existing credentials and retrieves a new one even if valid credentials exist. * @param callback the callback that will receive a valid [Credentials] or the [CredentialsManagerException]. */ - public fun getCredentials( + override fun getCredentials( scope: String?, minTtl: Int, parameters: Map, @@ -242,7 +242,7 @@ public class CredentialsManager @VisibleForTesting(otherwise = VisibleForTesting * @param forceRefresh this will avoid returning the existing credentials and retrieves a new one even if valid credentials exist. * @param callback the callback that will receive a valid [Credentials] or the [CredentialsManagerException]. */ - public fun getCredentials( + override fun getCredentials( scope: String?, minTtl: Int, parameters: Map, diff --git a/auth0/src/main/java/com/auth0/android/authentication/storage/SecureCredentialsManager.kt b/auth0/src/main/java/com/auth0/android/authentication/storage/SecureCredentialsManager.kt index a713c317c..fcbe4aefe 100644 --- a/auth0/src/main/java/com/auth0/android/authentication/storage/SecureCredentialsManager.kt +++ b/auth0/src/main/java/com/auth0/android/authentication/storage/SecureCredentialsManager.kt @@ -139,7 +139,7 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT */ @JvmSynthetic @Throws(CredentialsManagerException::class) - public suspend fun awaitCredentials(): Credentials { + override suspend fun awaitCredentials(): Credentials { return awaitCredentials(null, 0) } @@ -157,7 +157,7 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT */ @JvmSynthetic @Throws(CredentialsManagerException::class) - public suspend fun awaitCredentials( + override suspend fun awaitCredentials( scope: String?, minTtl: Int ): Credentials { @@ -179,7 +179,7 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT */ @JvmSynthetic @Throws(CredentialsManagerException::class) - public suspend fun awaitCredentials( + override suspend fun awaitCredentials( scope: String?, minTtl: Int, parameters: Map @@ -208,7 +208,7 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT */ @JvmSynthetic @Throws(CredentialsManagerException::class) - public suspend fun awaitCredentials( + override suspend fun awaitCredentials( scope: String?, minTtl: Int, parameters: Map, @@ -240,7 +240,7 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT */ @JvmSynthetic @Throws(CredentialsManagerException::class) - public suspend fun awaitCredentials( + override suspend fun awaitCredentials( scope: String?, minTtl: Int, parameters: Map, @@ -315,7 +315,7 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT * @param parameters additional parameters to send in the request to refresh expired credentials * @param callback the callback to receive the result in. */ - public fun getCredentials( + override fun getCredentials( scope: String?, minTtl: Int, parameters: Map, @@ -345,7 +345,7 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT * @param forceRefresh this will avoid returning the existing credentials and retrieves a new one even if valid credentials exist. * @param callback the callback to receive the result in. */ - public fun getCredentials( + override fun getCredentials( scope: String?, minTtl: Int, parameters: Map, @@ -377,7 +377,7 @@ public class SecureCredentialsManager @VisibleForTesting(otherwise = VisibleForT * @param forceRefresh this will avoid returning the existing credentials and retrieves a new one even if valid credentials exist. * @param callback the callback to receive the result in. */ - public fun getCredentials( + override fun getCredentials( scope: String?, minTtl: Int, parameters: Map, diff --git a/auth0/src/main/java/com/auth0/android/management/UsersAPIClient.kt b/auth0/src/main/java/com/auth0/android/management/UsersAPIClient.kt index 135f9ae95..43f23af44 100755 --- a/auth0/src/main/java/com/auth0/android/management/UsersAPIClient.kt +++ b/auth0/src/main/java/com/auth0/android/management/UsersAPIClient.kt @@ -3,6 +3,7 @@ package com.auth0.android.management import androidx.annotation.VisibleForTesting import com.auth0.android.Auth0 import com.auth0.android.Auth0Exception +import com.auth0.android.NetworkErrorException import com.auth0.android.authentication.ParameterBuilder import com.auth0.android.request.ErrorAdapter import com.auth0.android.request.JsonAdapter @@ -14,6 +15,7 @@ import com.auth0.android.request.internal.GsonAdapter.Companion.forListOf import com.auth0.android.request.internal.GsonAdapter.Companion.forMap import com.auth0.android.request.internal.GsonProvider import com.auth0.android.request.internal.RequestFactory +import com.auth0.android.request.internal.ResponseUtils.isNetworkError import com.auth0.android.result.UserIdentity import com.auth0.android.result.UserProfile import com.google.gson.Gson @@ -219,6 +221,12 @@ public class UsersAPIClient @VisibleForTesting(otherwise = VisibleForTesting.PRI } override fun fromException(cause: Throwable): ManagementException { + if (isNetworkError(cause)) { + return ManagementException( + "Failed to execute the network request", + NetworkErrorException(cause) + ) + } return ManagementException( "Something went wrong", Auth0Exception("Something went wrong", cause) diff --git a/auth0/src/main/java/com/auth0/android/request/DefaultClient.kt b/auth0/src/main/java/com/auth0/android/request/DefaultClient.kt index c0c676b6d..a00a57d8c 100644 --- a/auth0/src/main/java/com/auth0/android/request/DefaultClient.kt +++ b/auth0/src/main/java/com/auth0/android/request/DefaultClient.kt @@ -24,6 +24,7 @@ public class DefaultClient @VisibleForTesting(otherwise = VisibleForTesting.PRIV readTimeout: Int, private val defaultHeaders: Map, enableLogging: Boolean, + private val gson: Gson, sslSocketFactory: SSLSocketFactory?, trustManager: X509TrustManager? ) : NetworkingClient { @@ -40,11 +41,8 @@ public class DefaultClient @VisibleForTesting(otherwise = VisibleForTesting.PRIV connectTimeout: Int = DEFAULT_TIMEOUT_SECONDS, readTimeout: Int = DEFAULT_TIMEOUT_SECONDS, defaultHeaders: Map = mapOf(), - enableLogging: Boolean = false - ) : this(connectTimeout, readTimeout, defaultHeaders, enableLogging, null, null) - - //TODO: receive this via internal constructor parameters - private val gson: Gson = GsonProvider.gson + enableLogging: Boolean = false, + ) : this(connectTimeout, readTimeout, defaultHeaders, enableLogging, GsonProvider.gson, null, null) @get:VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) internal val okHttpClient: OkHttpClient @@ -71,6 +69,7 @@ public class DefaultClient @VisibleForTesting(otherwise = VisibleForTesting.PRIV .map { urlBuilder.addQueryParameter(it.key, it.value as String) } requestBuilder.method(options.method.toString(), null) } + else -> { // add parameters as body val body = gson.toJson(options.parameters).toRequestBody(APPLICATION_JSON_UTF8) @@ -90,7 +89,6 @@ public class DefaultClient @VisibleForTesting(otherwise = VisibleForTesting.PRIV val builder = OkHttpClient.Builder() // logging - //TODO: OFF by default! if (enableLogging) { val logger: Interceptor = HttpLoggingInterceptor() .setLevel(HttpLoggingInterceptor.Level.BODY) diff --git a/auth0/src/main/java/com/auth0/android/request/Request.kt b/auth0/src/main/java/com/auth0/android/request/Request.kt index 7bba4a29a..e6825e9f5 100755 --- a/auth0/src/main/java/com/auth0/android/request/Request.kt +++ b/auth0/src/main/java/com/auth0/android/request/Request.kt @@ -21,10 +21,6 @@ public interface Request { * Performs an async HTTP request against Auth0 API inside a Coroutine * This is a Coroutine that is exposed only for Kotlin. * - * Note: This method was added after the interface was released. - * It is defined as a default method for compatibility reasons. - * From version 3.0 on, the method will be abstract and all implementations of this interface - * will have to provide their own implementation. * * The default implementation throws an [UnsupportedOperationException]. * @@ -32,9 +28,7 @@ public interface Request { */ @JvmSynthetic @Throws(Auth0Exception::class) - public suspend fun await(): T { - throw UnsupportedOperationException("await") - } + public suspend fun await(): T /** * Executes the HTTP request against Auth0 API (blocking the current thread) diff --git a/auth0/src/main/java/com/auth0/android/request/internal/ResponseUtils.java b/auth0/src/main/java/com/auth0/android/request/internal/ResponseUtils.java deleted file mode 100644 index 6b9ae5e1a..000000000 --- a/auth0/src/main/java/com/auth0/android/request/internal/ResponseUtils.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.auth0.android.request.internal; - -import java.io.Closeable; -import java.io.IOException; - -class ResponseUtils { - - /** - * Attempts to close a stream. No exception will be thrown if an IOException was raised. - * - * @param closeable the stream to close - */ - static void closeStream(Closeable closeable) { - try { - closeable.close(); - } catch (IOException ignored) { - } - } -} diff --git a/auth0/src/main/java/com/auth0/android/request/internal/ResponseUtils.kt b/auth0/src/main/java/com/auth0/android/request/internal/ResponseUtils.kt new file mode 100644 index 000000000..fc80234b1 --- /dev/null +++ b/auth0/src/main/java/com/auth0/android/request/internal/ResponseUtils.kt @@ -0,0 +1,29 @@ +package com.auth0.android.request.internal + +import java.io.Closeable +import java.io.IOException +import java.net.SocketException +import java.net.SocketTimeoutException +import java.net.UnknownHostException + +internal object ResponseUtils { + /** + * Attempts to close a stream. No exception will be thrown if an IOException was raised. + * + * @param closeable the stream to close + */ + fun closeStream(closeable: Closeable) { + try { + closeable.close() + } catch (ignored: IOException) { + } + } + + /** + * Checks if the given Throwable is a network error. + */ + fun isNetworkError(cause: Throwable?): Boolean { + return (cause is SocketException || cause is SocketTimeoutException + || cause is UnknownHostException) + } +} diff --git a/auth0/src/main/java/com/auth0/android/result/Credentials.kt b/auth0/src/main/java/com/auth0/android/result/Credentials.kt index 841665633..42904212f 100755 --- a/auth0/src/main/java/com/auth0/android/result/Credentials.kt +++ b/auth0/src/main/java/com/auth0/android/result/Credentials.kt @@ -1,6 +1,5 @@ package com.auth0.android.result -import androidx.annotation.VisibleForTesting import com.auth0.android.request.internal.GsonProvider import com.auth0.android.request.internal.Jwt import com.google.gson.annotations.SerializedName @@ -18,7 +17,7 @@ import java.util.* * * *scope*: The token's granted scope. * */ -public open class Credentials( +public data class Credentials( /** * Getter for the Identity Token with user information. * @@ -61,11 +60,6 @@ public open class Credentials( @field:SerializedName("scope") public val scope: String? ) { - //TODO this could be removed and the class be a data class instead - @get:VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - internal open val currentTimeInMillis: Long - get() = System.currentTimeMillis() - /** * Getter for the new multi-factor authentication recovery code. Only available if these credentials are the result of logging in using an MFA recovery code. * @@ -79,10 +73,11 @@ public open class Credentials( return "Credentials(idToken='xxxxx', accessToken='xxxxx', type='$type', refreshToken='xxxxx', expiresAt='$expiresAt', scope='$scope')" } - public val user: UserProfile get() { - val (_, payload) = Jwt.splitToken(idToken) - val gson = GsonProvider.gson - return gson.fromJson(Jwt.decodeBase64(payload), UserProfile::class.java) - } + public val user: UserProfile + get() { + val (_, payload) = Jwt.splitToken(idToken) + val gson = GsonProvider.gson + return gson.fromJson(Jwt.decodeBase64(payload), UserProfile::class.java) + } } \ No newline at end of file diff --git a/auth0/src/test/java/com/auth0/android/authentication/AuthenticationExceptionTest.kt b/auth0/src/test/java/com/auth0/android/authentication/AuthenticationExceptionTest.kt index 97c37343b..e1bb2cfb9 100644 --- a/auth0/src/test/java/com/auth0/android/authentication/AuthenticationExceptionTest.kt +++ b/auth0/src/test/java/com/auth0/android/authentication/AuthenticationExceptionTest.kt @@ -205,7 +205,7 @@ public class AuthenticationExceptionTest { @Test public fun shouldHaveNetworkErrorForSocketTimeout() { val ex = AuthenticationException( - "Request has definitely failed", Auth0Exception("", + "Request has definitely failed", NetworkErrorException( SocketTimeoutException() ) ) diff --git a/auth0/src/test/java/com/auth0/android/authentication/storage/CredentialsManagerTest.kt b/auth0/src/test/java/com/auth0/android/authentication/storage/CredentialsManagerTest.kt index eda4d1adb..98c4faff6 100644 --- a/auth0/src/test/java/com/auth0/android/authentication/storage/CredentialsManagerTest.kt +++ b/auth0/src/test/java/com/auth0/android/authentication/storage/CredentialsManagerTest.kt @@ -73,7 +73,7 @@ public class CredentialsManagerTest { val refreshToken = invocation.getArgument(3, String::class.java) val expiresAt = invocation.getArgument(4, Date::class.java) val scope = invocation.getArgument(5, String::class.java) - CredentialsMock(idToken, accessToken, type, refreshToken, expiresAt, scope) + CredentialsMock.create(idToken, accessToken, type, refreshToken, expiresAt, scope) }.`when`(manager).recreateCredentials( ArgumentMatchers.anyString(), ArgumentMatchers.anyString(), @@ -87,7 +87,7 @@ public class CredentialsManagerTest { @Test public fun shouldSaveRefreshableCredentialsInStorage() { val expirationTime = CredentialsMock.ONE_HOUR_AHEAD_MS - val credentials: Credentials = CredentialsMock( + val credentials: Credentials = CredentialsMock.create( "idToken", "accessToken", "type", @@ -110,7 +110,7 @@ public class CredentialsManagerTest { @Test public fun shouldSaveRefreshableCredentialsUsingAccessTokenExpForCacheExpirationInStorage() { val accessTokenExpirationTime = CredentialsMock.ONE_HOUR_AHEAD_MS - val credentials: Credentials = CredentialsMock( + val credentials: Credentials = CredentialsMock.create( "", "accessToken", "type", @@ -134,7 +134,7 @@ public class CredentialsManagerTest { public fun shouldSaveRefreshableCredentialsIgnoringIdTokenExpForCacheExpirationInStorage() { val accessTokenExpirationTime = CredentialsMock.CURRENT_TIME_MS + 5000 * 1000 val idTokenExpirationTime = CredentialsMock.CURRENT_TIME_MS + 2000 * 1000 - val credentials: Credentials = CredentialsMock( + val credentials: Credentials = CredentialsMock.create( "idToken", "accessToken", "type", @@ -158,7 +158,14 @@ public class CredentialsManagerTest { public fun shouldSaveNonRefreshableCredentialsInStorage() { val expirationTime = CredentialsMock.ONE_HOUR_AHEAD_MS val credentials: Credentials = - CredentialsMock("idToken", "accessToken", "type", null, Date(expirationTime), "scope") + CredentialsMock.create( + "idToken", + "accessToken", + "type", + null, + Date(expirationTime), + "scope" + ) prepareJwtDecoderMock(Date(expirationTime)) manager.saveCredentials(credentials) verify(storage).store("com.auth0.id_token", "idToken") @@ -176,21 +183,21 @@ public class CredentialsManagerTest { exception.expect(CredentialsManagerException::class.java) exception.expectMessage("Credentials must have a valid access_token or id_token value.") val credentials: Credentials = - CredentialsMock("", "", "type", "refreshToken", Date(), null) + CredentialsMock.create("", "", "type", "refreshToken", Date(), null) manager.saveCredentials(credentials) } @Test public fun shouldNotThrowOnSetIfCredentialsHasAccessTokenAndExpiresAt() { val credentials: Credentials = - CredentialsMock("", "accessToken", "type", "refreshToken", Date(), null) + CredentialsMock.create("", "accessToken", "type", "refreshToken", Date(), null) manager.saveCredentials(credentials) } @Test public fun shouldNotThrowOnSetIfCredentialsHasIdTokenAndExpiresAt() { val credentials: Credentials = - CredentialsMock("idToken", "", "type", "refreshToken", Date(), null) + CredentialsMock.create("idToken", "", "type", "refreshToken", Date(), null) prepareJwtDecoderMock(Date()) manager.saveCredentials(credentials) } @@ -946,8 +953,8 @@ public class CredentialsManagerTest { throw IllegalArgumentException("Proper Executor Set") } manager.getCredentials(object : Callback { - override fun onSuccess(result: Credentials) { } - override fun onFailure(error: CredentialsManagerException) { } + override fun onSuccess(result: Credentials) {} + override fun onFailure(error: CredentialsManagerException) {} }) } @@ -1024,12 +1031,21 @@ public class CredentialsManagerTest { verify(callback).onSuccess(credentialsCaptor.capture()) val retrievedCredentials = credentialsCaptor.firstValue MatcherAssert.assertThat(retrievedCredentials, Is.`is`(Matchers.notNullValue())) - MatcherAssert.assertThat(retrievedCredentials.accessToken, Is.`is`(expectedCredentials.accessToken)) + MatcherAssert.assertThat( + retrievedCredentials.accessToken, + Is.`is`(expectedCredentials.accessToken) + ) MatcherAssert.assertThat(retrievedCredentials.idToken, Is.`is`(expectedCredentials.idToken)) - MatcherAssert.assertThat(retrievedCredentials.refreshToken, Is.`is`(expectedCredentials.refreshToken)) + MatcherAssert.assertThat( + retrievedCredentials.refreshToken, + Is.`is`(expectedCredentials.refreshToken) + ) MatcherAssert.assertThat(retrievedCredentials.type, Is.`is`(expectedCredentials.type)) MatcherAssert.assertThat(retrievedCredentials.expiresAt, Is.`is`(Matchers.notNullValue())) - MatcherAssert.assertThat(retrievedCredentials.expiresAt.time, Is.`is`(expectedCredentials.expiresAt.time)) + MatcherAssert.assertThat( + retrievedCredentials.expiresAt.time, + Is.`is`(expectedCredentials.expiresAt.time) + ) MatcherAssert.assertThat(retrievedCredentials.scope, Is.`is`(expectedCredentials.scope)) } @@ -1045,7 +1061,8 @@ public class CredentialsManagerTest { Mockito.`when`(storage.retrieveLong("com.auth0.cache_expires_at")) .thenReturn(expirationTime) Mockito.`when`(storage.retrieveString("com.auth0.scope")).thenReturn("scope") - manager.getCredentials("scope", + manager.getCredentials( + "scope", 0, emptyMap(), false, diff --git a/auth0/src/test/java/com/auth0/android/authentication/storage/SecureCredentialsManagerTest.kt b/auth0/src/test/java/com/auth0/android/authentication/storage/SecureCredentialsManagerTest.kt index 6aae7de70..8cd78a89f 100644 --- a/auth0/src/test/java/com/auth0/android/authentication/storage/SecureCredentialsManagerTest.kt +++ b/auth0/src/test/java/com/auth0/android/authentication/storage/SecureCredentialsManagerTest.kt @@ -163,7 +163,7 @@ public class SecureCredentialsManagerTest { @Test public fun shouldSaveRefreshableCredentialsInStorage() { val sharedExpirationTime = CredentialsMock.ONE_HOUR_AHEAD_MS - val credentials: Credentials = CredentialsMock( + val credentials: Credentials = CredentialsMock.create( "idToken", "accessToken", "type", @@ -198,7 +198,7 @@ public class SecureCredentialsManagerTest { @Test public fun shouldSaveRefreshableCredentialsUsingAccessTokenExpForCacheExpirationInStorage() { val accessTokenExpirationTime = CredentialsMock.ONE_HOUR_AHEAD_MS - val credentials: Credentials = CredentialsMock( + val credentials: Credentials = CredentialsMock.create( "", "accessToken", "type", @@ -237,7 +237,7 @@ public class SecureCredentialsManagerTest { public fun shouldSaveRefreshableCredentialsIgnoringIdTokenExpForCacheExpirationInStorage() { val accessTokenExpirationTime = CredentialsMock.ONE_HOUR_AHEAD_MS val idTokenExpirationTime = CredentialsMock.CURRENT_TIME_MS + 2000 * 1000 - val credentials: Credentials = CredentialsMock( + val credentials: Credentials = CredentialsMock.create( "idToken", "accessToken", "type", @@ -276,7 +276,14 @@ public class SecureCredentialsManagerTest { public fun shouldSaveNonRefreshableCredentialsInStorage() { val expirationTime = CredentialsMock.ONE_HOUR_AHEAD_MS val credentials: Credentials = - CredentialsMock("idToken", "accessToken", "type", null, Date(expirationTime), "scope") + CredentialsMock.create( + "idToken", + "accessToken", + "type", + null, + Date(expirationTime), + "scope" + ) val json = gson.toJson(credentials) prepareJwtDecoderMock(Date(expirationTime)) Mockito.`when`(crypto.encrypt(json.toByteArray())).thenReturn(json.toByteArray()) @@ -304,7 +311,7 @@ public class SecureCredentialsManagerTest { @Test public fun shouldClearStoredCredentialsAndThrowOnSaveOnCryptoException() { val expirationTime = CredentialsMock.ONE_HOUR_AHEAD_MS - val credentials: Credentials = CredentialsMock( + val credentials: Credentials = CredentialsMock.create( "idToken", "accessToken", "type", @@ -336,7 +343,7 @@ public class SecureCredentialsManagerTest { @Test public fun shouldThrowOnSaveOnIncompatibleDeviceException() { val expirationTime = CredentialsMock.ONE_HOUR_AHEAD_MS - val credentials: Credentials = CredentialsMock( + val credentials: Credentials = CredentialsMock.create( "idToken", "accessToken", "type", @@ -366,14 +373,14 @@ public class SecureCredentialsManagerTest { exception.expect(CredentialsManagerException::class.java) exception.expectMessage("Credentials must have a valid access_token or id_token value.") val credentials: Credentials = - CredentialsMock("", "", "type", "refreshToken", Date(), "scope") + CredentialsMock.create("", "", "type", "refreshToken", Date(), "scope") manager.saveCredentials(credentials) } @Test public fun shouldNotThrowOnSaveIfCredentialsHaveAccessTokenAndExpiresIn() { val credentials: Credentials = - CredentialsMock("", "accessToken", "type", "refreshToken", Date(), "scope") + CredentialsMock.create("", "accessToken", "type", "refreshToken", Date(), "scope") Mockito.`when`(crypto.encrypt(any())) .thenReturn(byteArrayOf(12, 34, 56, 78)) manager.saveCredentials(credentials) @@ -382,7 +389,7 @@ public class SecureCredentialsManagerTest { @Test public fun shouldNotThrowOnSaveIfCredentialsHaveIdTokenAndExpiresIn() { val credentials: Credentials = - CredentialsMock("idToken", "", "type", "refreshToken", Date(), "scope") + CredentialsMock.create("idToken", "", "type", "refreshToken", Date(), "scope") prepareJwtDecoderMock(Date()) Mockito.`when`(crypto.encrypt(any())) .thenReturn(byteArrayOf(12, 34, 56, 78)) diff --git a/auth0/src/test/java/com/auth0/android/request/DefaultClientTest.kt b/auth0/src/test/java/com/auth0/android/request/DefaultClientTest.kt index 4f1e19020..a30ca88bc 100644 --- a/auth0/src/test/java/com/auth0/android/request/DefaultClientTest.kt +++ b/auth0/src/test/java/com/auth0/android/request/DefaultClientTest.kt @@ -306,6 +306,7 @@ public class DefaultClientTest { readTimeout = 10, connectTimeout = 10, enableLogging = false, + gson = gson, sslSocketFactory = SSLTestUtils.clientCertificates.sslSocketFactory(), trustManager = SSLTestUtils.clientCertificates.trustManager ) diff --git a/auth0/src/test/java/com/auth0/android/request/internal/CredentialsDeserializerMock.kt b/auth0/src/test/java/com/auth0/android/request/internal/CredentialsDeserializerMock.kt index 52d745462..b2ade84c6 100644 --- a/auth0/src/test/java/com/auth0/android/request/internal/CredentialsDeserializerMock.kt +++ b/auth0/src/test/java/com/auth0/android/request/internal/CredentialsDeserializerMock.kt @@ -15,7 +15,7 @@ internal class CredentialsDeserializerMock : CredentialsDeserializer() { recoveryCode: String? ): Credentials { val credentials = - CredentialsMock(idToken, accessToken, type, refreshToken, expiresAt, scope) + CredentialsMock.create(idToken, accessToken, type, refreshToken, expiresAt, scope) credentials.recoveryCode = recoveryCode return credentials } diff --git a/auth0/src/test/java/com/auth0/android/request/internal/CredentialsGsonTest.kt b/auth0/src/test/java/com/auth0/android/request/internal/CredentialsGsonTest.kt index 6813a2a54..d10df32a5 100755 --- a/auth0/src/test/java/com/auth0/android/request/internal/CredentialsGsonTest.kt +++ b/auth0/src/test/java/com/auth0/android/request/internal/CredentialsGsonTest.kt @@ -120,7 +120,7 @@ public class CredentialsGsonTest : GsonBaseTest() { val expiresAt = Date(CredentialsMock.CURRENT_TIME_MS + 123456 * 1000) val expectedExpiresAt = formatDate(expiresAt) val expiresInCredentials: Credentials = - CredentialsMock("id", "access", "ty", "refresh", expiresAt, null) + CredentialsMock.create("id", "access", "ty", "refresh", expiresAt, null) val expiresInJson = gson.toJson(expiresInCredentials) MatcherAssert.assertThat(expiresInJson, CoreMatchers.containsString("\"id_token\":\"id\"")) MatcherAssert.assertThat( @@ -149,7 +149,7 @@ public class CredentialsGsonTest : GsonBaseTest() { CoreMatchers.not(CoreMatchers.containsString("\"scope\"")) ) val expiresAtCredentials: Credentials = - CredentialsMock("id", "access", "ty", "refresh", expiresAt, "openid") + CredentialsMock.create("id", "access", "ty", "refresh", expiresAt, "openid") val expiresAtJson = gson.toJson(expiresAtCredentials) MatcherAssert.assertThat(expiresAtJson, CoreMatchers.containsString("\"id_token\":\"id\"")) MatcherAssert.assertThat( diff --git a/auth0/src/test/java/com/auth0/android/request/internal/ResponseUtilsTest.kt b/auth0/src/test/java/com/auth0/android/request/internal/ResponseUtilsTest.kt new file mode 100644 index 000000000..14dd8855a --- /dev/null +++ b/auth0/src/test/java/com/auth0/android/request/internal/ResponseUtilsTest.kt @@ -0,0 +1,27 @@ +package com.auth0.android.request.internal + +import junit.framework.TestCase.assertTrue +import org.hamcrest.CoreMatchers +import org.hamcrest.MatcherAssert +import org.junit.Test +import java.net.SocketException +import java.net.SocketTimeoutException +import java.net.UnknownHostException + +public class ResponseUtilsTest { + + @Test + public fun testIsNetworkErrorWhenSocketExceptionOccurs() { + MatcherAssert.assertThat(ResponseUtils.isNetworkError(SocketException()), CoreMatchers.`is`(true)) + } + + @Test + public fun testIsNetworkErrorWhenSocketTimeoutExceptionOccurs() { + MatcherAssert.assertThat(ResponseUtils.isNetworkError(SocketTimeoutException()), CoreMatchers.`is`(true)) + } + + @Test + public fun testIsNetworkErrorWhenUnknownHostExceptionOccurs() { + MatcherAssert.assertThat(ResponseUtils.isNetworkError(UnknownHostException()), CoreMatchers.`is`(true)) + } +} \ No newline at end of file diff --git a/auth0/src/test/java/com/auth0/android/result/CredentialsMock.kt b/auth0/src/test/java/com/auth0/android/result/CredentialsMock.kt index c60371c5c..50dd8b41b 100644 --- a/auth0/src/test/java/com/auth0/android/result/CredentialsMock.kt +++ b/auth0/src/test/java/com/auth0/android/result/CredentialsMock.kt @@ -2,17 +2,7 @@ package com.auth0.android.result import java.util.* -public class CredentialsMock( - idToken: String, - accessToken: String, - type: String, - refreshToken: String?, - expiresAt: Date, - scope: String? -) : Credentials(idToken, accessToken, type, refreshToken, expiresAt, scope) { - - override val currentTimeInMillis: Long - get() = CURRENT_TIME_MS +public class CredentialsMock { public companion object { @JvmField @@ -26,5 +16,16 @@ public class CredentialsMock( cal.timeZone = TimeZone.getTimeZone("UTC") return cal.timeInMillis } + + public fun create( + idToken: String, + accessToken: String, + type: String, + refreshToken: String?, + expiresAt: Date, + scope: String? + ): Credentials { + return Credentials(idToken, accessToken, type, refreshToken, expiresAt, scope) + } } } \ No newline at end of file diff --git a/auth0/src/test/java/com/auth0/android/result/CredentialsTest.kt b/auth0/src/test/java/com/auth0/android/result/CredentialsTest.kt index cd40d358d..ac38dc36b 100644 --- a/auth0/src/test/java/com/auth0/android/result/CredentialsTest.kt +++ b/auth0/src/test/java/com/auth0/android/result/CredentialsTest.kt @@ -6,10 +6,10 @@ import org.hamcrest.Matchers import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner -import java.text.SimpleDateFormat import java.util.* -private val idToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbXktZG9tYWluLmF1dGgwLmNvbSIsInN1YiI6ImF1dGgwfDEyMzQ1NiIsImF1ZCI6Im15X2NsaWVudF9pZCIsImV4cCI6MTMxMTI4MTk3MCwiaWF0IjoxMzExMjgwOTcwLCJuYW1lIjoiSmFuZSBEb2UiLCJnaXZlbl9uYW1lIjoiSmFuZSIsImZhbWlseV9uYW1lIjoiRG9lIiwiZ2VuZGVyIjoiZmVtYWxlIiwiYmlydGhkYXRlIjoiMDAwMC0xMC0zMSIsImVtYWlsIjoiamFuZWRvZUBleGFtcGxlLmNvbSIsInBpY3R1cmUiOiJodHRwOi8vZXhhbXBsZS5jb20vamFuZWRvZS9tZS5qcGcifQ.FKw0UVWANEqibD9VTC9WLzstlyc_IRnyPSpUMDP3hKc" +private val idToken = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbXktZG9tYWluLmF1dGgwLmNvbSIsInN1YiI6ImF1dGgwfDEyMzQ1NiIsImF1ZCI6Im15X2NsaWVudF9pZCIsImV4cCI6MTMxMTI4MTk3MCwiaWF0IjoxMzExMjgwOTcwLCJuYW1lIjoiSmFuZSBEb2UiLCJnaXZlbl9uYW1lIjoiSmFuZSIsImZhbWlseV9uYW1lIjoiRG9lIiwiZ2VuZGVyIjoiZmVtYWxlIiwiYmlydGhkYXRlIjoiMDAwMC0xMC0zMSIsImVtYWlsIjoiamFuZWRvZUBleGFtcGxlLmNvbSIsInBpY3R1cmUiOiJodHRwOi8vZXhhbXBsZS5jb20vamFuZWRvZS9tZS5qcGcifQ.FKw0UVWANEqibD9VTC9WLzstlyc_IRnyPSpUMDP3hKc" @RunWith(RobolectricTestRunner::class) public class CredentialsTest { @@ -17,7 +17,7 @@ public class CredentialsTest { public fun shouldCreate() { val date = Date() val credentials: Credentials = - CredentialsMock("idToken", "accessToken", "type", "refreshToken", date, "scope") + CredentialsMock.create("idToken", "accessToken", "type", "refreshToken", date, "scope") MatcherAssert.assertThat(credentials.idToken, Matchers.`is`("idToken")) MatcherAssert.assertThat(credentials.accessToken, Matchers.`is`("accessToken")) MatcherAssert.assertThat(credentials.type, Matchers.`is`("type")) @@ -38,7 +38,7 @@ public class CredentialsTest { public fun shouldGetRecoveryCode() { val date = Date() val credentials: Credentials = - CredentialsMock("idToken", "accessToken", "type", "refreshToken", date, "scope") + CredentialsMock.create("idToken", "accessToken", "type", "refreshToken", date, "scope") credentials.recoveryCode = "recoveryCode" MatcherAssert.assertThat(credentials.recoveryCode, Matchers.`is`("recoveryCode")) } @@ -47,12 +47,15 @@ public class CredentialsTest { public fun shouldGetUser() { val date = Date() val credentials: Credentials = - CredentialsMock(idToken, "accessToken", "type", "refreshToken", date, "scope") + CredentialsMock.create(idToken, "accessToken", "type", "refreshToken", date, "scope") MatcherAssert.assertThat(credentials.user.getId(), Matchers.`is`("auth0|123456")) MatcherAssert.assertThat(credentials.user.name, Matchers.`is`("Jane Doe")) MatcherAssert.assertThat(credentials.user.givenName, Matchers.`is`("Jane")) MatcherAssert.assertThat(credentials.user.familyName, Matchers.`is`("Doe")) - MatcherAssert.assertThat(credentials.user.pictureURL, Matchers.`is`("http://example.com/janedoe/me.jpg")) + MatcherAssert.assertThat( + credentials.user.pictureURL, + Matchers.`is`("http://example.com/janedoe/me.jpg") + ) MatcherAssert.assertThat(credentials.user.email, Matchers.`is`("janedoe@example.com")) } @@ -60,7 +63,7 @@ public class CredentialsTest { public fun shouldNotSerializeUser() { val date = Date() val credentials: Credentials = - CredentialsMock(idToken, "accessToken", "type", "refreshToken", date, "scope") + CredentialsMock.create(idToken, "accessToken", "type", "refreshToken", date, "scope") MatcherAssert.assertThat(credentials.user.getId(), Matchers.`is`("auth0|123456")) val json = gson.toJson(credentials, Credentials::class.java) MatcherAssert.assertThat(json, Matchers.not(Matchers.containsString("auth0|123456"))) @@ -72,7 +75,10 @@ public class CredentialsTest { public fun shouldNotPrintCredentials() { val date = Date() val credentials: Credentials = - CredentialsMock(idToken, "accessToken", "type", "refreshToken", date, "scope") - MatcherAssert.assertThat(credentials.toString(), Matchers.`is`("Credentials(idToken='xxxxx', accessToken='xxxxx', type='type', refreshToken='xxxxx', expiresAt='$date', scope='scope')")) + CredentialsMock.create(idToken, "accessToken", "type", "refreshToken", date, "scope") + MatcherAssert.assertThat( + credentials.toString(), + Matchers.`is`("Credentials(idToken='xxxxx', accessToken='xxxxx', type='type', refreshToken='xxxxx', expiresAt='$date', scope='scope')") + ) } } \ No newline at end of file diff --git a/auth0/src/test/java/com/auth0/android/util/SSLTestUtils.kt b/auth0/src/test/java/com/auth0/android/util/SSLTestUtils.kt index ac0128cfa..542a8e4b6 100644 --- a/auth0/src/test/java/com/auth0/android/util/SSLTestUtils.kt +++ b/auth0/src/test/java/com/auth0/android/util/SSLTestUtils.kt @@ -1,6 +1,7 @@ package com.auth0.android.util import com.auth0.android.request.DefaultClient +import com.auth0.android.request.internal.GsonProvider import okhttp3.mockwebserver.MockWebServer import okhttp3.tls.HandshakeCertificates import okhttp3.tls.HeldCertificate @@ -35,6 +36,7 @@ internal object SSLTestUtils { readTimeout = 10, connectTimeout = 10, enableLogging = false, + gson = GsonProvider.gson, sslSocketFactory = clientCertificates.sslSocketFactory(), trustManager = clientCertificates.trustManager )