Skip to content

[NAPP-167] Fix the Guardian.Android sample app so it compiles and is ready for integration tests - #206

Merged
arunav-gandhi merged 2 commits into
masterfrom
feature/NAPP-167
Oct 30, 2026
Merged

arunav-gandhi merged 2 commits into
masterfrom
feature/NAPP-167

Conversation

@arunav-gandhi

@arunav-gandhi arunav-gandhi commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Description

Fixes the :app sample so it builds on the current Android toolchain and is ready to host the SDK's integration tests (NAPP-167).

The SDK (:guardian) is not touched. guardian/, build.sh, tools/, the release workflows and the publishing config have no changes. The release dependency tree, the
generated POM and every class in the AAR are identical to master (verified by building both and diffing).

Background

The :app sample is the only end-to-end consumer of the SDK, but nothing built it: build.sh and the fastlane lanes only assemble the library, and the SCA scan
excludes app. It had drifted: it used the removed FirebaseInstanceId API, old dependencies, SDK 33 and Java 8, had a hardcoded tenant URL, and used deprecated APIs
(startActivityForResult, PreferenceManager, un-flagged PendingIntent). This brings it back and adds a CI job so it cannot silently break again.

What changed

Build and toolchain

  • compileSdk/targetSdk 36 and Java 17. minSdk is 24 for the app only, because firebase-messaging 26 requires it; the SDK keeps minSdk 22, compileSdk 33 and Java 8.
  • Firebase BoM 35.1.0 without firebase-core; Material, Gson, ZXing and the google-services plugin updated; explicit appcompat, activity and core; buildConfig enabled explicitly.
  • FCM token via FirebaseMessaging.getInstance().getToken(). That API is deprecated since messaging 25.1 in favour of FID registration; it is kept (with a note) because Guardian enrolls with an FCM token.
  • Kotlin plugin 2.4.21 applied to :app only. The three small helpers (SampleGuardian, SystemBars, EnrollmentStorage) are Kotlin objects with @JvmStatic members, so the Java activities call them unchanged. The rest of the sample and the SDK stay Java.

Behaviour on the new target

  • Activity Result API for enrollment and the camera and notification permissions; POST_NOTIFICATIONS; a notification channel; an immutable, per-transaction PendingIntent; edge-to-edge insets (forced at target 35+).
  • Pushes received while the app is in the background now become notifications. Before, MainActivity stayed subscribed to EventBus, so the push was swallowed and the activity start was blocked on Android 10+.
  • Fixes found along the way: rotating re-opened the request screen; a stale notification crashed MainActivity; the consent fetch updated the UI off the main thread; the enroll screen crashed on devices without a back camera; DialogCallback leaked the windows of destroyed activities.
  • HTTP logging is debug-only (request/response bodies carry the bearer token, TOTP secret and transaction tokens). Cloud backup and device transfer are disabled, because the enrollment, including its private key, lives in SharedPreferences.

Ready for integration tests

  • The tenant URL is configurable with -PguardianTenantUrl, ~/.gradle/gradle.properties or GUARDIAN_TENANT_URL. It is validated as https and exposed as
    BuildConfig.TENANT_URL and the tenantUrl instrumentation argument. The hardcoded guardian.xml is gone.
  • IDs and content descriptions on the enroll, QR scan and allow/deny controls (each description contains the visible label).
  • An "Enter enrollment link" button and dialog (it opens automatically when the device has no camera), the Android analogue of the paste-link enrollment in
    Guardian.swift#184, plus an ENROLLMENT_DATA intent extra for instrumentation tests (EnrollActivity is not exported).
  • The committed app/google-services.json is a dummy placeholder and stays on purpose, so a clean clone and CI can build. A real file goes in the git-ignored
    app/src/debug/google-services.json. app/README.md documents configuration, the manual test flow and the test hooks.

CI

  • A new sample job ("Build sample app") in pr.yml, parallel to test, runs the new fastlane android build_sample lane (:app:assembleDebug). A failing lint or coverage
    step can no longer hide a broken sample, and the reverse. This mirrors Guardian.swift#184.

Alternatives considered

  • CI step: a build.sh --sample flag chained into the existing step. Rejected in favour of a separate job: independent result, runs in parallel, and it matches the
    iOS PR.
  • QR scanner: replacing the legacy android.hardware.Camera scanner with CameraX. Not needed: it still compiles and runs at target 36. Left as a follow-up.
  • :guardian to SDK 36 / Java 17: not done here (Robolectric 4.14 tops out at API 35); separate ticket.
  • Kotlin: only the three new helper classes are converted. A full migration belongs with the CameraX follow-up.

References

Testing

How to test

  1. ./gradlew :app:assembleDebug from a clean clone, then ./gradlew :app:lintDebug (0 errors).
  2. bundle exec fastlane android build_sample (what the new CI job runs). Break :app on purpose and it exits non-zero.
  3. Optional, on a device or emulator with Google Play services: ./gradlew :app:installDebug -PguardianTenantUrl=https://, then follow "Manual test flow" in app/README.md. With the placeholder google-services.json the main-screen Enroll button is not reachable (the app reports it cannot get an FCM token); supply a real app/src/debug/google-services.json for that, or use the paste-link dialog.

Verified locally

  • :app:assembleDebug passes from a clean copy of the repo; :app:lintDebug has 0 errors.
  • fastlane android build_sample passes.
  • SDK unaffected: git diff origin/master -- guardian build.sh tools is empty; the :guardian release dependency tree, generated POM, manifest and all 42 AAR classes are identical to master (built both and compared); the 182 :guardian unit tests pass.
  • Emulator (API 37, Google APIs): launch, notification permission prompt, rotation and backgrounding; the paste-link dialog (a bad link reaches the SDK, the server answers 401, the error is shown and the screen stays open); the link button is reachable with the camera permission denied; the dialog survives rotation; leaving the screen or rotating mid-request does not crash or leak a window.

Checklist

  • I have added documentation for new/changed functionality in this PR or in auth0.com/docs
  • All active GitHub checks for tests, formatting, and security are passing
  • The correct base branch is being used, if not the default branch

arunav-gandhi and others added 2 commits October 29, 2026 19:36
…on tests

The :app sample was the only end-to-end consumer of the SDK, but nothing
built it, so it had drifted: it used the removed FirebaseInstanceId API
and old dependencies, targeted SDK 33 and Java 8, and had a hardcoded
tenant. The SDK (:guardian) is not touched.

Build and toolchain
- compileSdk/targetSdk 36, Java 17, minSdk 24 (firebase-messaging 26
  requires 24). Firebase BoM 35.1.0 without firebase-core, Material,
  Gson, ZXing, google-services plugin bumped; explicit appcompat,
  activity and core. buildConfig enabled explicitly.
- FCM token via FirebaseMessaging.getToken() (deprecated in 25.1+ in favour
  of FID registration; kept with a note because Guardian enrolls with an
  FCM token).

Behaviour on the new target
- Activity Result API for enrollment and the camera and notification
  permissions; POST_NOTIFICATIONS; notification channel and immutable,
  per-transaction PendingIntent; edge-to-edge insets.
- Pushes while the app is in the background now become notifications
  (EventBus is only registered while visible).
- Fixes found along the way: rotation re-opening the request screen,
  stale notifications crashing MainActivity, consent fetch off the main
  thread, crash on devices without a camera, DialogCallback leaking
  windows of dead activities.
- HTTP logging only in debug builds (bodies carry tokens and secrets);
  backup and device transfer disabled (the enrollment holds the key).

Ready for integration tests
- Tenant URL configurable (-PguardianTenantUrl, gradle.properties or
  GUARDIAN_TENANT_URL), exposed as BuildConfig.TENANT_URL and the
  tenantUrl instrumentation argument.
- Content descriptions and IDs on the enroll, QR scan, allow and deny
  controls; "Enter enrollment link" button and dialog for devices
  without a usable camera; ENROLLMENT_DATA intent extra for tests.
- app/README.md explains configuration, the placeholder
  google-services.json (kept on purpose) and how to supply a real one.

CI
- New "sample" job in pr.yml, parallel to "test", running the new
  `fastlane android build_sample` lane (:app:assembleDebug), mirroring
  Guardian.swift#184.

Co-Authored-By: Claude <noreply@anthropic.com>
Apply the Kotlin Gradle plugin (2.4.21, which supports AGP 8.12.2 and
Gradle 8.13) to :app only and convert the three small helpers added in
this PR from Java to Kotlin objects:

- SampleGuardian: builds the Guardian client, HTTP logging debug-only.
- SystemBars: edge-to-edge insets helper (enableEdgeToEdge).
- EnrollmentStorage: load/save the enrollment in SharedPreferences.

Each is an `object` with @JvmStatic members, so the Java activities call
them unchanged. The rest of the sample and :guardian stay Java; the
kotlin-gradle-plugin is only on the root buildscript classpath.

Verified: the :guardian release dependency tree, generated POM, manifest
and all 42 classes in the AAR are identical to origin/master; 182 SDK unit
tests pass; :app builds with 0 lint errors; fastlane build_sample passes.

Co-Authored-By: Claude <noreply@anthropic.com>
@arunav-gandhi arunav-gandhi changed the title [NAPP-167] Fix the sample app so it builds and is ready for integrati… [NAPP-167] Fix the Guardian.Android sample app so it compiles and is ready for integration tests Oct 29, 2026
@arunav-gandhi
arunav-gandhi merged commit 21bf531 into master Oct 30, 2026
5 checks passed
@arunav-gandhi
arunav-gandhi deleted the feature/NAPP-167 branch October 30, 2026 05:37
arunav-gandhi added a commit that referenced this pull request Nov 11, 2026
#188, #202, #204, #205 and #206 landed after the entry was drafted on Oct 21.

Co-Authored-By: Claude <noreply@anthropic.com>
arunav-gandhi added a commit that referenced this pull request Nov 11, 2026
* [NAPP-244] Fix jackson and java-jwt CVEs (ESD-71218)

Bump com.auth0:java-jwt 4.6.1 -> 4.6.2 and the jackson-bom pin 2.22.2 -> 2.22.4,
and declare jackson-core / jackson-databind directly (explicit 2.22.4) so Maven
consumers and POM-only scanners also resolve the patched version. java-jwt 4.6.2
still pulls Jackson 2.22.3, which is affected by CVE-2026-110879.

Addresses CVE-2026-85473 (java-jwt), CVE-2026-89425 and CVE-2026-89407
(jackson-core), CVE-2026-91776, CVE-2026-91777 and CVE-2026-110879
(jackson-databind).

Co-Authored-By: Claude <noreply@anthropic.com>

* [NAPP-244] Add Security entry to the 0.11.3 CHANGELOG section

Prepare release does not rewrite an existing CHANGELOG entry (correction mode),
so record the jackson / java-jwt CVE fixes here and update the date.

Co-Authored-By: Claude <noreply@anthropic.com>

* [NAPP-244] Add PRs merged since the 0.11.3 CHANGELOG entry was generated

#188, #202, #204, #205 and #206 landed after the entry was drafted on Oct 21.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants