diff --git a/README.md b/README.md index 5c910adc..28a3baa5 100644 --- a/README.md +++ b/README.md @@ -117,11 +117,11 @@ Next, define the Manifest Placeholders for the Auth0 Domain and Scheme which are apply plugin: 'com.android.application' android { - compileSdkVersion 35 + compileSdkVersion 36 defaultConfig { applicationId "com.auth0.samples" minSdkVersion 24 - targetSdkVersion 35 + targetSdkVersion 36 //... //---> Add the next line diff --git a/V4_MIGRATION_GUIDE.md b/V4_MIGRATION_GUIDE.md index 6256f7be..b8ca744b 100644 --- a/V4_MIGRATION_GUIDE.md +++ b/V4_MIGRATION_GUIDE.md @@ -29,13 +29,13 @@ android { v4 requires: -- **Gradle**: 8.10.2 or later -- **Android Gradle Plugin (AGP)**: 8.8.2 or later +- **Gradle**: 8.11.1 or later +- **Android Gradle Plugin (AGP)**: 8.10.1 or later Update your `gradle/wrapper/gradle-wrapper.properties`: ```properties -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip ``` Update your root `build.gradle`: @@ -43,7 +43,7 @@ Update your root `build.gradle`: ```groovy buildscript { dependencies { - classpath 'com.android.tools.build:gradle:8.8.2' + classpath 'com.android.tools.build:gradle:8.10.1' } } ``` @@ -67,6 +67,34 @@ buildscript { - [signinWithPasskey()](auth0/src/main/java/com/auth0/android/authentication/AuthenticationAPIClient.kt#L235-L253) - Sign in a user using passkeys - [signupWithPasskey()](auth0/src/main/java/com/auth0/android/authentication/AuthenticationAPIClient.kt#L319-L344) - Sign up a user and returns a challenge for key generation +## Dependency Changes + +### ⚠️ Gson 2.8.9 → 2.11.0 (Transitive Dependency) + +v4 updates the internal Gson dependency from **2.8.9** to **2.11.0**. While the SDK does not expose Gson types in its public API, Gson is included as a transitive runtime dependency. If your app also uses Gson, be aware of the following changes introduced in Gson 2.10+: + +- **`TypeToken` with unresolved type variables is rejected at runtime.** Code like `object : TypeToken>() {}` (where `T` is a generic parameter) will throw `IllegalArgumentException`. Use Kotlin `reified` type parameters or pass concrete types instead. +- **Strict type coercion is enforced.** Gson no longer silently coerces JSON objects or arrays to `String`. If your code relies on this behavior, you will see `JsonSyntaxException`. +- **Built-in ProGuard/R8 rules are included.** Gson 2.11.0 ships its own keep rules, so you may be able to remove custom Gson ProGuard rules from your project. + +If you need to pin Gson to an older version, you can use Gradle's `resolutionStrategy`: + +```groovy +configurations.all { + resolutionStrategy.force 'com.google.code.gson:gson:2.8.9' +} +``` + +Alternatively, you can exclude Gson from the SDK entirely and provide your own version: + +```groovy +implementation('com.auth0.android:auth0:') { + exclude group: 'com.google.code.gson', module: 'gson' +} +implementation 'com.google.code.gson:gson:2.8.9' // your preferred version +``` + +> **Note:** Pinning or excluding is not recommended long-term, as the SDK has been tested and validated against Gson 2.11.0. ## Getting Help diff --git a/auth0/build.gradle b/auth0/build.gradle index 8c0d4650..28ff39fb 100644 --- a/auth0/build.gradle +++ b/auth0/build.gradle @@ -35,7 +35,7 @@ logger.lifecycle("Using version ${version} for ${name}") android { namespace 'com.auth0.android.auth0' - compileSdk 35 + compileSdk 36 buildFeatures { buildConfig = true @@ -43,7 +43,7 @@ android { defaultConfig { minSdkVersion 21 - targetSdk 35 + targetSdk 36 versionCode 1 versionName project.version @@ -81,34 +81,34 @@ android { ext { okhttpVersion = '4.12.0' - coroutinesVersion = '1.7.3' + coroutinesVersion = '1.10.2' biometricLibraryVersion = '1.1.0' } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation 'androidx.core:core-ktx:1.6.0' - implementation 'androidx.appcompat:appcompat:1.6.0' - implementation 'androidx.browser:browser:1.4.0' + implementation 'androidx.core:core-ktx:1.15.0' + implementation 'androidx.appcompat:appcompat:1.7.0' + implementation 'androidx.browser:browser:1.9.0' implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion" implementation "com.squareup.okhttp3:okhttp:$okhttpVersion" implementation "com.squareup.okhttp3:logging-interceptor:$okhttpVersion" - implementation 'com.google.code.gson:gson:2.8.9' - implementation 'com.google.androidbrowserhelper:androidbrowserhelper:2.4.0' + implementation 'com.google.code.gson:gson:2.11.0' + implementation 'com.google.androidbrowserhelper:androidbrowserhelper:2.5.0' implementation "androidx.biometric:biometric:$biometricLibraryVersion" testImplementation 'junit:junit:4.13.2' testImplementation 'org.hamcrest:java-hamcrest:2.0.0.0' - testImplementation 'org.mockito:mockito-core:5.7.0' - testImplementation 'org.mockito.kotlin:mockito-kotlin:5.1.0' + testImplementation 'org.mockito:mockito-core:5.14.0' + testImplementation 'org.mockito.kotlin:mockito-kotlin:5.4.0' testImplementation "com.squareup.okhttp3:mockwebserver:$okhttpVersion" testImplementation "com.squareup.okhttp3:okhttp-tls:$okhttpVersion" testImplementation 'com.jayway.awaitility:awaitility:1.7.0' - testImplementation 'org.robolectric:robolectric:4.14.1' - testImplementation 'androidx.test.espresso:espresso-intents:3.5.1' + testImplementation 'org.robolectric:robolectric:4.15.1' + testImplementation 'androidx.test.espresso:espresso-intents:3.6.1' testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion" testImplementation "androidx.biometric:biometric:$biometricLibraryVersion" diff --git a/auth0/src/test/java/com/auth0/android/authentication/AuthenticationAPIClientTest.kt b/auth0/src/test/java/com/auth0/android/authentication/AuthenticationAPIClientTest.kt index e83b7cc1..350ec5d2 100755 --- a/auth0/src/test/java/com/auth0/android/authentication/AuthenticationAPIClientTest.kt +++ b/auth0/src/test/java/com/auth0/android/authentication/AuthenticationAPIClientTest.kt @@ -225,7 +225,7 @@ public class AuthenticationAPIClientTest { defaultLocale ) ) - val body = bodyFromRequest(request) + val body = bodyFromRequest(request) assertThat(request.path, Matchers.equalTo("/oauth/token")) assertThat(body, Matchers.hasEntry("client_id", CLIENT_ID)) assertThat( @@ -254,7 +254,7 @@ public class AuthenticationAPIClientTest { defaultLocale ) ) - val body = bodyFromRequest(request) + val body = bodyFromRequest(request) assertThat(request.path, Matchers.equalTo("/passkey/register")) assertThat(body, Matchers.hasEntry("client_id", CLIENT_ID)) assertThat(body, Matchers.hasEntry("realm", MY_CONNECTION)) @@ -1034,7 +1034,7 @@ public class AuthenticationAPIClientTest { ) ) assertThat(request.path, Matchers.equalTo("/dbconnections/signup")) - val body = bodyFromRequest(request) + val body = bodyFromRequest(request) assertThat(body, Matchers.hasEntry("email", SUPPORT_AUTH0_COM)) assertThat(body, Matchers.hasEntry("username", SUPPORT)) assertThat(body, Matchers.hasEntry("password", PASSWORD)) @@ -1058,7 +1058,7 @@ public class AuthenticationAPIClientTest { ) ) assertThat(request.path, Matchers.equalTo("/dbconnections/signup")) - val body = bodyFromRequest(request) + val body = bodyFromRequest(request) assertThat(body, Matchers.hasEntry("email", SUPPORT_AUTH0_COM)) assertThat(body, Matchers.hasEntry("username", SUPPORT)) assertThat(body, Matchers.hasEntry("password", PASSWORD)) @@ -1361,7 +1361,7 @@ public class AuthenticationAPIClientTest { ) ) assertThat(request.path, Matchers.equalTo("/dbconnections/signup")) - val body = bodyFromRequest(request) + val body = bodyFromRequest(request) assertThat(body, Matchers.hasEntry("email", SUPPORT_AUTH0_COM)) assertThat(body, Matchers.hasEntry("username", SUPPORT)) assertThat(body, Matchers.hasEntry("password", PASSWORD)) @@ -3132,8 +3132,8 @@ public class AuthenticationAPIClientTest { assertThat(exception.cause, Matchers.instanceOf(DPoPException::class.java)) } - private fun bodyFromRequest(request: RecordedRequest): Map { - val mapType = object : TypeToken?>() {}.type + private inline fun bodyFromRequest(request: RecordedRequest): Map { + val mapType = object : TypeToken>() {}.type return gson.fromJson(request.body.readUtf8(), mapType) } diff --git a/auth0/src/test/java/com/auth0/android/management/UsersAPIClientTest.kt b/auth0/src/test/java/com/auth0/android/management/UsersAPIClientTest.kt index 64bc7e25..7c1d370e 100755 --- a/auth0/src/test/java/com/auth0/android/management/UsersAPIClientTest.kt +++ b/auth0/src/test/java/com/auth0/android/management/UsersAPIClientTest.kt @@ -441,8 +441,8 @@ public class UsersAPIClientTest { ) } - private fun bodyFromRequest(request: RecordedRequest): Map { - val mapType = object : TypeToken?>() {}.type + private inline fun bodyFromRequest(request: RecordedRequest): Map { + val mapType = object : TypeToken>() {}.type return gson.fromJson(request.body.readUtf8(), mapType) } diff --git a/auth0/src/test/java/com/auth0/android/myaccount/MyAccountAPIClientTest.kt b/auth0/src/test/java/com/auth0/android/myaccount/MyAccountAPIClientTest.kt index 41d647df..388530df 100644 --- a/auth0/src/test/java/com/auth0/android/myaccount/MyAccountAPIClientTest.kt +++ b/auth0/src/test/java/com/auth0/android/myaccount/MyAccountAPIClientTest.kt @@ -467,8 +467,8 @@ public class MyAccountAPIClientTest { assertThat(body, Matchers.hasEntry("type", "push-notification" as Any)) } - private fun bodyFromRequest(request: RecordedRequest): Map { - val mapType = object : TypeToken?>() {}.type + private inline fun bodyFromRequest(request: RecordedRequest): Map { + val mapType = object : TypeToken>() {}.type return gson.fromJson(request.body.readUtf8(), mapType) } diff --git a/build.gradle b/build.gradle index 1324eaed..7f94c35e 100644 --- a/build.gradle +++ b/build.gradle @@ -6,9 +6,9 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.8.2' + classpath 'com.android.tools.build:gradle:8.10.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "org.jacoco:org.jacoco.core:0.8.5" + classpath "org.jacoco:org.jacoco.core:0.8.12" } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 18330fcb..11581996 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/sample/build.gradle b/sample/build.gradle index c1246a84..85612cf9 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -5,11 +5,11 @@ plugins { android { namespace 'com.auth0.sample' - compileSdk 35 + compileSdk 36 defaultConfig { minSdk 24 - targetSdk 35 + targetSdk 36 versionCode 1 versionName "1.0"