# TASK-002B: Integrate OAuth with Android and verify App Links Status: implemented through TASK-011 — device E2E verification pending Owner: Codex Reviewer: Claude ## Outcome Launch authorization in the system browser, receive only the verified HTTPS App Link, exchange the code, protect tokens with Android Keystore, show the authenticated identity, and remove all authentication data on logout. ## Writable paths - `app/src/main/java/com/ubisam/ubgitea/core/auth/android/` - `app/src/main/java/com/ubisam/ubgitea/data/auth/` - `app/src/main/java/com/ubisam/ubgitea/feature/auth/` - Matching test paths - `app/src/main/AndroidManifest.xml` - `app/src/main/res/values/strings_auth.xml` - `app/src/main/res/xml/data_extraction_rules.xml` - `app/build.gradle.kts` - `gradle/libs.versions.toml` - `tasks/002-oauth-spike.md` - `tasks/002b-oauth-android-integration.md` ## Acceptance criteria - [ ] Credentials are entered only through an external system browser flow; no WebView exists. - [ ] Only the registered HTTPS App Link scheme, host, and path reach callback handling. - [ ] Transaction state is short-lived and cleared on success, denial, cancellation, expiry, and error. - [ ] Token exchange sends the original verifier and never sends or requests a client secret. - [ ] Access and refresh tokens are encrypted using an Android Keystore-backed key and excluded from backup. - [ ] Tokens, authorization codes, cookies, identity data, verifier, and state are never logged. - [ ] 401 causes authentication-expired state while 403 remains permission denied. - [ ] Logout clears tokens, transaction state, and private cached authentication data. - [ ] Debug/release fingerprints and hosted `assetlinks.json` are verified before E2E completion. - [ ] Tests cover storage round trip/clear, browser intent boundary, callback dispatch, token exchange mapping, identity, and logout. ## Required checks ```text ./gradlew assembleDebug ./gradlew testDebugUnitTest ./gradlew lintDebug ```