Skip to content

Commit 58fb8d1

Browse files
authored
Merge pull request #104 from logto-io/simeng-chore-bump-deps-for-agp9-support
chore: modernize dependencies and android tooling
1 parent 23444f9 commit 58fb8d1

21 files changed

Lines changed: 705 additions & 133 deletions

.github/workflows/main.yml

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,106 @@ jobs:
5959
with:
6060
flags: Dart-sdk
6161
directory: ./lib
62+
63+
build-android:
64+
runs-on: ubuntu-latest
65+
66+
steps:
67+
- uses: actions/checkout@v4
68+
69+
- name: Setup Java
70+
uses: actions/setup-java@v4
71+
with:
72+
distribution: temurin
73+
java-version: 17
74+
75+
- name: Setup Flutter
76+
uses: subosito/flutter-action@v2
77+
with:
78+
channel: stable
79+
80+
- name: Install
81+
run: flutter pub get
82+
83+
- name: Build example APK
84+
working-directory: ./example
85+
run: flutter build apk --debug
86+
87+
# Verifies that tokens written by SDK 3.x (flutter_secure_storage 9.x, Jetpack
88+
# EncryptedSharedPreferences) are still readable after upgrading to 4.0. This is what
89+
# keeps the flutter_secure_storage constraint from being raised past 10.x: 11.x
90+
# deleted the migration bridge, and losing it signs existing Android users out
91+
# silently. Needs a real device, hence the emulator.
92+
token-migration:
93+
runs-on: ubuntu-latest
94+
95+
steps:
96+
- uses: actions/checkout@v4
97+
98+
- name: Setup Java
99+
uses: actions/setup-java@v4
100+
with:
101+
distribution: temurin
102+
java-version: 17
103+
104+
- name: Setup Flutter
105+
uses: subosito/flutter-action@v2
106+
with:
107+
channel: stable
108+
109+
- name: Enable KVM
110+
run: |
111+
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
112+
| sudo tee /etc/udev/rules.d/99-kvm4all.rules
113+
sudo udevadm control --reload-rules
114+
sudo udevadm trigger --name-match=kvm
115+
116+
- name: Run token migration upgrade test
117+
uses: reactivecircus/android-emulator-runner@v2
118+
with:
119+
api-level: 33
120+
arch: x86_64
121+
disable-animations: true
122+
script: ./tool/test_token_migration.sh
123+
124+
# Validates the `environment.flutter` floor declared in pubspec.yaml. The example app
125+
# ships an AGP 9 configuration (built-in Kotlin), which the floor release predates, so
126+
# the Android project is reverted to the toolchain a Flutter 3.35 app would generate
127+
# before building. Keep FLUTTER_FLOOR in sync with `environment.flutter`.
128+
build-android-floor:
129+
runs-on: ubuntu-latest
130+
131+
env:
132+
FLUTTER_FLOOR: 3.35.0
133+
AGP_FLOOR: 8.9.1
134+
GRADLE_FLOOR: 8.12
135+
136+
steps:
137+
- uses: actions/checkout@v4
138+
139+
- name: Setup Java
140+
uses: actions/setup-java@v4
141+
with:
142+
distribution: temurin
143+
java-version: 17
144+
145+
- name: Setup Flutter
146+
uses: subosito/flutter-action@v2
147+
with:
148+
channel: stable
149+
flutter-version: ${{ env.FLUTTER_FLOOR }}
150+
151+
- name: Restore pre-AGP-9 android configuration
152+
working-directory: ./example/android
153+
run: |
154+
sed -i "s/id \"com.android.application\" version \"[0-9.]*\"/id \"com.android.application\" version \"$AGP_FLOOR\"/" settings.gradle
155+
sed -i "s|gradle-[0-9.]*-all.zip|gradle-$GRADLE_FLOOR-all.zip|" gradle/wrapper/gradle-wrapper.properties
156+
sed -i "s|^ id \"com.android.application\"$| id \"com.android.application\"\n id \"kotlin-android\"|" app/build.gradle
157+
sed -i "/^# This newDsl flag/,+3d" gradle.properties
158+
159+
- name: Install
160+
run: flutter pub get
161+
162+
- name: Build example APK
163+
working-directory: ./example
164+
run: flutter build apk --debug

CHANGELOG.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,54 @@
1+
## 4.0.0
2+
3+
Modernizes the dependency stack so apps keep building on recent Flutter and Android
4+
toolchains. **No Dart API changed in this release, and existing users stay signed in**
5+
tokens stored by `3.x` are migrated automatically on first read.
6+
7+
### What you need to do
8+
9+
All of the required work is in your app's Android configuration. See the
10+
[3.x to 4.0 migration guide](https://github.com/logto-io/dart#upgrading-from-3x-to-40)
11+
for copy-pasteable snippets.
12+
13+
| Change | Where |
14+
| ------ | ----- |
15+
| Flutter `>=3.35.0`, Dart `^3.9.0` | your toolchain |
16+
| Android Gradle Plugin `>=8.9.1` | `android/settings.gradle` |
17+
| `compileSdk 36`, `minSdk 24` — both are the Flutter 3.35+ defaults, so no change if you use them | `android/app/build.gradle` |
18+
| `android:taskAffinity=""` on exported activities | `android/app/src/main/AndroidManifest.xml` |
19+
20+
Upgrading from a version before `3.0.0` lands you on `4.0.0` directly, so the
21+
[pre-3.0 migration steps](https://github.com/logto-io/dart#upgrading-from-a-version-before-300)
22+
(manifest rename, `signOut` now requiring `redirectUri`) apply **in addition to** the table
23+
above — not instead of it.
24+
25+
### Dependencies update
26+
27+
Starting with Android Gradle Plugin (AGP) 9.0, applying the Kotlin Gradle Plugin (KGP) from a
28+
plugin is no longer supported, which breaks builds that depend on older plugin versions.
29+
([Flutter migration guide](https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin))
30+
31+
1. Bump `flutter_secure_storage` from `^9.0.0` to `^10.3.1`
32+
33+
- `10.x` no longer applies the Kotlin Gradle Plugin, which is what unblocks AGP 9 builds.
34+
- The Android implementation no longer uses the deprecated Jetpack `encryptedSharedPreferences` backend. Tokens written by SDK `3.x` are read and migrated to the new AES-GCM cipher storage on first access, since `migrateOnAlgorithmChange` defaults to true. Existing users stay signed in across the upgrade.
35+
- Android now requires `minSdkVersion` 24 (`flutter_secure_storage` needs 23; `flutter_web_auth_2` and the Flutter 3.35 default raise it to 24).
36+
37+
> **Note**: this SDK intentionally stays on `flutter_secure_storage` `10.x` rather than `11.x`. The `11.x` release removed the `EncryptedSharedPreferences` backend outright, so upgrading directly from `9.x` to `11.x` makes tokens written by SDK `3.x` unreadable and silently signs existing Android users out — verified on a device, where the same read returns `null` under `11.0.0` and the original value under `10.3.1`. `10.x` is the migration bridge, and `tool/test_token_migration.sh` guards it. A future major release will move to `11.x` once users have had a release to migrate through; note that the bridge only helps users who actually run a `4.x` release, so anyone upgrading `3.x` straight to that future major would still be signed out.
38+
39+
2. Bump `flutter_web_auth_2` from `^4.1.0` to `^5.1.0`
40+
41+
- This plugin does not raise the iOS or macOS deployment floor: its podspecs still target iOS 11.0 / macOS 10.15. The SDK's floors of iOS 13.0 / macOS 10.15 come from Flutter 3.35 itself. iOS 17.4 / macOS 14.4 are needed only for HTTPS (universal link) callbacks — `flutter_web_auth_2` gates `ASWebAuthenticationSession.Callback` behind `#available` and falls back to the `callbackURLScheme:` initializer below those versions, which is the path this SDK uses with `callbackUrlScheme`.
42+
- It is strongly advised to set `android:taskAffinity=""` on all exported activities (including your `MainActivity` and the `flutter_web_auth_2` `CallbackActivity`) in the AndroidManifest.xml file. See the updated example app.
43+
44+
3. Bump `jose` to `^0.3.5+1`, which resolves [GHSA-vm9r-h74p-hg97](https://github.com/advisories/GHSA-vm9r-h74p-hg97) (untrusted JWK header key acceptance during signature verification). This SDK uses `jose` to verify ID tokens, so the dependency floor is raised rather than only the lockfile.
45+
46+
4. Require Dart SDK `^3.9.0` and Flutter `>=3.35.0`.
47+
48+
This floor is set by the Android toolchain, not by the Dart-level constraints. `flutter_web_auth_2` `5.1.0` compiles against SDK 36 and depends on `androidx.browser:browser:1.9.0`, whose AAR metadata declares `minCompileSdk=36` and `minAndroidGradlePluginVersion=8.9.1`. Flutter `3.35.0` is the first release whose template ships AGP `8.9.1` and defaults `flutter.compileSdkVersion` to 36; on Flutter `3.24` (template AGP `7.3.0`, `compileSdk 34`) the build fails at `:app:checkDebugAarMetadata`. Apps that pin their own AGP must be on `8.9.1+` with `compileSdk 36`.
49+
50+
> **Note**: `flutter_web_auth_2` `5.x` still applies the Kotlin Gradle Plugin on Android, so it does not yet build with AGP 9. Flutter's temporary KGP compatibility keeps it working on current Flutter releases. Full AGP 9 support lands in `flutter_web_auth_2` `6.x` (in alpha at the time of writing), which we will adopt once it is stable.
51+
152
## 3.0.0
253

354
### Dependencies update

README.md

Lines changed: 153 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
# Logto Flutter SDK
1010

11-
[![Build Status](https://github.com/logto-io/kotlin/actions/workflows/main.yml/badge.svg)](https://github.com/logto-io/dart/actions/workflows/main.yml)
11+
[![Build Status](https://github.com/logto-io/dart/actions/workflows/main.yml/badge.svg)](https://github.com/logto-io/dart/actions/workflows/main.yml)
1212

1313
This project is the official Flutter SDK for [Logto](https://logto.io). It provides a simple way to integrate Logto into your Flutter project.
1414

@@ -20,7 +20,7 @@ Add the following dependencies to your `pubspec.yaml` file:
2020

2121
```yaml
2222
dependencies:
23-
logto_dart_sdk: ^3.0.0
23+
logto_dart_sdk: ^4.0.0
2424
```
2525
2626
Then run `flutter pub get` to install the package.
@@ -35,10 +35,18 @@ Check out the package on [pub.dev](https://pub.dev/packages/logto_dart_sdk).
3535

3636
## Setup
3737

38-
- iOS: No additional setup required.
39-
- [Android](https://github.com/ThexXTURBOXx/flutter_web_auth_2?tab=readme-ov-file#android).
40-
- [Web](https://github.com/ThexXTURBOXx/flutter_web_auth_2?tab=readme-ov-file#web)
38+
Check [Minimum requirements](#minimum-requirements) first — this SDK requires Flutter 3.35.0+
39+
and, on Android, AGP 8.9.1+ with `compileSdk 36` and `minSdkVersion 24`.
4140

41+
- **iOS**: no additional setup required.
42+
- **Android**: register the callback activity in your `AndroidManifest.xml` and set
43+
`android:taskAffinity=""` on your exported activities — see
44+
[Upgrading from 3.x to 4.0](#upgrading-from-3x-to-40) for the exact snippets, or the
45+
[flutter_web_auth_2 Android notes](https://github.com/ThexXTURBOXx/flutter_web_auth_2?tab=readme-ov-file#android).
46+
- **Web**: serve a callback endpoint that posts the result back to the app — see the
47+
[flutter_web_auth_2 web notes](https://github.com/ThexXTURBOXx/flutter_web_auth_2?tab=readme-ov-file#web).
48+
49+
The [example app](./example) is a complete working reference for all three platforms.
4250
Learn more about the [flutter_web_auth_2 setup](https://github.com/ThexXTURBOXx/flutter_web_auth_2?tab=readme-ov-file#setup).
4351

4452
## Usages
@@ -78,27 +86,158 @@ Check [Flutter SDK guide](https://docs.logto.io/quick-starts/flutter) for more d
7886

7987
iOS, Android, Web
8088

89+
## Minimum requirements
90+
91+
| Requirement | Version |
92+
| ----------- | ------- |
93+
| Dart SDK | 3.9.0 |
94+
| Flutter | 3.35.0 |
95+
| Android Gradle Plugin | 8.9.1 |
96+
| Android | `compileSdk 36`, `minSdkVersion 24` |
97+
| iOS | 13.0 |
98+
| macOS | 10.15 |
99+
100+
The Android floor is set by `flutter_web_auth_2` 5.x, which compiles against SDK 36 and pulls
101+
`androidx.browser:browser:1.9.0` (`minCompileSdk=36`, `minAndroidGradlePluginVersion=8.9.1`).
102+
Flutter 3.35.0 is the first release whose template ships AGP 8.9.1 and defaults
103+
`flutter.compileSdkVersion` to 36, so earlier Flutter versions fail at
104+
`:app:checkDebugAarMetadata` even though the Dart-level constraints resolve.
105+
106+
The iOS and macOS floors are set by Flutter 3.35 itself, not by the plugins — Flutter 3.35
107+
targets iOS 13.0 / macOS 10.15, while the plugins allow lower (`flutter_secure_storage`
108+
iOS 12.0 / macOS 10.14, `flutter_web_auth_2` iOS 11.0 / macOS 10.15). Building on a newer
109+
Flutter raises these further (3.47 targets iOS 15.0 / macOS 12.0); that follows from the
110+
Flutter version you choose, not from this SDK.
111+
112+
**iOS 17.4 / macOS 14.4 are only required for HTTPS (universal link) callbacks.**
113+
`flutter_web_auth_2` gates `ASWebAuthenticationSession.Callback` behind
114+
`#available(iOS 17.4, *)` / `#available(macOS 14.4, *)` and falls back to the
115+
`callbackURLScheme:` initializer below those versions. This SDK passes `callbackUrlScheme`,
116+
so a custom-scheme redirect such as `io.logto://callback` works on the floors above.
117+
81118
## Migration guide
82119

120+
### Upgrading from 3.x to 4.0
121+
122+
**No Dart API changed, and your users stay signed in.** `signIn`, `signOut` and the rest keep
123+
their 3.x signatures, and tokens stored by 3.x are migrated to the new encrypted format the
124+
first time they are read, so nobody is forced to re-authenticate. The work is in your app's
125+
Android toolchain configuration.
126+
127+
1. Update the dependency:
128+
129+
```yaml
130+
dependencies:
131+
logto_dart_sdk: ^4.0.0
132+
```
133+
134+
2. Update Flutter and Dart to at least the versions in [Minimum requirements](#minimum-requirements)
135+
(Flutter 3.35.0 / Dart 3.9.0).
136+
137+
3. Use Android Gradle Plugin 8.9.1 or newer, in `android/settings.gradle`:
138+
139+
```groovy
140+
plugins {
141+
id "com.android.application" version "8.9.1" apply false
142+
}
143+
```
144+
145+
4. Make sure `android/app/build.gradle` resolves to `compileSdk 36` and `minSdk 24`. On
146+
Flutter 3.35+ the Flutter defaults already do, so **if you use them, no change is
147+
needed**:
148+
149+
```groovy
150+
android {
151+
compileSdk = flutter.compileSdkVersion // 36 on Flutter 3.35+
152+
153+
defaultConfig {
154+
minSdk = flutter.minSdkVersion // 24 on Flutter 3.35+
155+
}
156+
}
157+
```
158+
159+
If you pin either value explicitly, raise it:
160+
161+
```groovy
162+
android {
163+
compileSdk = 36
164+
165+
defaultConfig {
166+
minSdk = 24
167+
}
168+
}
169+
```
170+
171+
5. Add `android:taskAffinity=""` to every exported activity in
172+
`android/app/src/main/AndroidManifest.xml` — both your `MainActivity` and the
173+
`flutter_web_auth_2` `CallbackActivity`. This is strongly advised by `flutter_web_auth_2`
174+
5.x; without it the sign-in callback can return to the wrong task:
175+
176+
```xml
177+
<activity
178+
android:name=".MainActivity"
179+
android:exported="true"
180+
android:launchMode="singleTop"
181+
android:taskAffinity="">
182+
<!-- ... -->
183+
</activity>
184+
185+
<activity
186+
android:name="com.linusu.flutter_web_auth_2.CallbackActivity"
187+
android:exported="true"
188+
android:launchMode="singleTop"
189+
android:taskAffinity="">
190+
<!-- ... -->
191+
</activity>
192+
```
193+
194+
See the [example app](./example/android) for a complete working configuration — but note it
195+
targets AGP 9, so it does not apply `kotlin-android`. On AGP 8.x you still need that plugin in
196+
`android/app/build.gradle`; only remove it once you move to AGP 9 and Flutter's built-in Kotlin
197+
support. See Flutter's
198+
[built-in Kotlin migration guide](https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-app-developers).
199+
200+
#### A note on Android Gradle Plugin 9
201+
202+
AGP 9 removed support for plugins applying the Kotlin Gradle Plugin (KGP). That is what this
203+
release addresses: `flutter_secure_storage` 10.x no longer applies KGP, so it no longer blocks
204+
AGP 9 builds.
205+
206+
`flutter_web_auth_2` 5.x still applies KGP. Builds currently succeed because Flutter ships
207+
temporary KGP compatibility, and you will see this warning during the build:
208+
209+
```
210+
WARNING: Your app uses the following plugins that apply Kotlin Gradle Plugin (KGP): flutter_web_auth_2
211+
```
212+
213+
That warning is expected and harmless for now. Full AGP 9 support requires `flutter_web_auth_2`
214+
6.x, which is still in alpha at the time of writing; this SDK will adopt it once it is stable.
215+
216+
### Upgrading from a version before 3.0.0
217+
218+
> **Both sections apply.** Upgrading from 2.x lands you on 4.0, so complete
219+
> [Upgrading from 3.x to 4.0](#upgrading-from-3x-to-40) above — Flutter 3.35, AGP 8.9.1,
220+
> `compileSdk 36` / `minSdk 24`, and `android:taskAffinity=""` — **and** the additional changes
221+
> below. Skipping the 4.0 steps leaves Android either failing to build or returning the sign-in
222+
> callback to the wrong task.
223+
83224
:::note
84-
For SDK version before 3.0.0, this SDK uses the [flutter_web_auth](https://pub.dev/packages/flutter_web_auth) package.
225+
For SDK versions before 3.0.0, this SDK uses the [flutter_web_auth](https://pub.dev/packages/flutter_web_auth) package.
85226
:::
86227

87-
1. Upgrade to the latest version
228+
These changes are on top of the 3.x to 4.0 steps; the dependency bump is covered there.
88229

89-
```yaml
90-
dependencies:
91-
logto_dart_sdk: ^3.0.0
92-
```
93-
94-
2. Update the manifest files (Android platform only)
230+
1. Update the manifest files (Android platform only)
95231

96232
Replace the flutter_web_auth callback activity with the new `flutter_web_auth_2` in the AndroidManifest.xml file.
97233

98234
- FlutterWebAuth -> FlutterWebAuth2
99235
- flutter_web_auth -> flutter_web_auth_2
100236

101-
3. `redirectUri` parameter is now required for the `signOut` method.
237+
The `CallbackActivity` you end up with should also carry the `android:taskAffinity=""` and
238+
`android:launchMode="singleTop"` attributes from step 5 of the 4.0 section.
239+
240+
2. `redirectUri` parameter is now required for the `signOut` method.
102241

103242
```dart
104243
await logtoClient.signOut(redirectUri);

analysis_options.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
analyzer:
2+
exclude:
3+
- build/**
4+
- android/**
5+
- ios/**
6+
- web/**
7+
- windows/**
8+
- macos/**
9+
- linux/**
110
include: package:flutter_lints/flutter.yaml
211

312
# Additional information about this file can be found at

0 commit comments

Comments
 (0)