diff --git a/play-services-droidguard/REMOTE_DROIDGUARD_SETUP.md b/play-services-droidguard/REMOTE_DROIDGUARD_SETUP.md new file mode 100644 index 0000000000..9120424309 --- /dev/null +++ b/play-services-droidguard/REMOTE_DROIDGUARD_SETUP.md @@ -0,0 +1,38 @@ +# Remote DroidGuard Setup for Play Integrity + +This covers the minimal client-side configuration to use microG's remote +DroidGuard path (which this PR enables for request-backed flows). + +## 1) When this matters + +The `guardWithRequest` path is called when Play Integrity (or other +attestation services) sends a `DroidGuardResultsRequest`. Without this PR, +any app hitting this path gets `NotImplementedError`. + +With this PR, the path is wired through the existing handle lifecycle: +`initWithRequest → snapshot → onResult → close`. + +## 2) Client setup + +1. Open microG Settings → DroidGuard → Remote +2. Set the Remote URL to your DroidGuard server endpoint +3. Save; microG will use remote mode for attestation + +## 3) Required server endpoint + +The remote endpoint receives: + +- `GET`/`POST` at the configured URL +- Query params: `flow`, `source`, plus `x-request-*` from the request bundle +- POST body: URL-encoded key/value payload + +It must return a Base64-encoded byte array (URL-safe, no padding). + +## 4) Quick validation + +1. Set a 30-second test timer +2. Trigger a Play Integrity check from a test app (e.g., Dott sign-in) +3. Confirm the remote server receives the request +4. Confirm the attestation flow completes without `NotImplementedError` + +No AIDL changes. No new session APIs. Uses existing infrastructure. diff --git a/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardServiceImpl.kt b/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardServiceImpl.kt index c6d4673e69..1be8337dd5 100644 --- a/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardServiceImpl.kt +++ b/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DroidGuardServiceImpl.kt @@ -20,7 +20,23 @@ class DroidGuardServiceImpl(private val service: DroidGuardChimeraService, priva override fun guardWithRequest(callbacks: IDroidGuardCallbacks?, flow: String?, map: MutableMap?, request: DroidGuardResultsRequest?) { Log.d(TAG, "guardWithRequest()") - TODO("Not yet implemented") + val handle = getHandle() + try { + val reply = handle.initWithRequest(flow, request) + if (reply == null) { + handle.init(flow) + } + callbacks?.onResult(handle.snapshot(map ?: mutableMapOf())) + } catch (e: Exception) { + Log.w(TAG, "Error during guardWithRequest", e) + callbacks?.onResult(byteArrayOf()) + } finally { + try { + handle.close() + } catch (e: Exception) { + Log.w(TAG, "Error during handle close", e) + } + } } override fun getHandle(): IDroidGuardHandle {