microg/GmsCore · error · SecurityException

client not admin, yet tried to enable work authenticator

Error message

client not admin, yet tried to enable work authenticator

What it means

UnauthorizedWorkAccountServiceImpl.setWorkAuthenticatorEnabled unconditionally throws this SecurityException. This stub is returned to clients that are not authorized to manage work accounts (not an admin/delegated caller), so any attempt to toggle the work authenticator through it always fails by design — it is an intentional authorization guard, not a bug.

Source

Thrown at play-services-auth-workaccount/core/src/main/kotlin/org/microg/gms/auth/workaccount/WorkAccountService.kt:138

                    Intent(WORK_ACCOUNT_CHANGED_BOARDCAST).setPackage("com.android.vending")
                )

                callback?.onAccountRemoved(success)
            } else {
                val future = accountManager.removeAccount(it, null, null)
                Thread {
                    future.result.let { result ->
                        callback?.onAccountRemoved(result)
                    }
                }.start()
            }
        }
    }
}

class UnauthorizedWorkAccountServiceImpl : IWorkAccountService.Stub() {
    override fun setWorkAuthenticatorEnabled(enabled: Boolean) {
        throw SecurityException("client not admin, yet tried to enable work authenticator")
    }

    override fun addWorkAccount(callback: IWorkAccountCallback?, token: String?) {
        throw SecurityException("client not admin, yet tried to add work account")
    }

    override fun removeWorkAccount(callback: IWorkAccountCallback?, account: Account?) {
        throw SecurityException("client not admin, yet tried to remove work account")
    }
}

View on GitHub (pinned to 157c9d86ac)

Solutions

  1. Become an authorized caller: the client must satisfy the service's admin/authorization check (e.g. hold the required system/admin permission or be the designated authenticator admin)
  2. Use the Android AccountManager work-authenticator APIs available to regular apps instead of the restricted service
  3. Catch SecurityException and degrade gracefully (inform the user work-account management is unavailable)
  4. Request device-owner/admin provisioning if work-account administration is genuinely required

Example fix

// before
workAccountService.setWorkAuthenticatorEnabled(true)
// after
try {
    workAccountService.setWorkAuthenticatorEnabled(true)
} catch (e: SecurityException) {
    Log.w(TAG, "Not authorized to manage work authenticator", e)
}
Defensive patterns

Strategy: try-catch

Validate before calling

val authorized = ctx.checkCallingOrSelfPermission(ADMIN_PERMISSION) == PackageManager.PERMISSION_GRANTED // per service policy

Try / catch

try { svc.setWorkAuthenticatorEnabled(true) } catch (e: SecurityException) { showNotAuthorizedUi() }

Prevention

When it happens

Trigger: Calling setWorkAuthenticatorEnabled(true/false) via IWorkAccountService when the bound implementation is UnauthorizedWorkAccountServiceImpl, i.e. the caller lacks the admin/authorization the service requires.

Common situations: A third-party app binding to the microG work-account service without being an authorized admin client; calling the work authenticator API from a non-device-owner context; attempting work-account management without the required system/admin privileges.

Understand the failure class

Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.

Related errors


AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06). Data as JSON: /api/errors/9dc9d6169d78ef83. Report an issue: GitHub.