I'm developing in Android some apps that will share autentication and auth tokens received from an auth-server. I would like to use a android custom account as suggested here: https://developer.android.com/training/id-auth/custom_auth so that the user is added in the Settings -> Accounts and then all authorized apps can access the auth tokens.
Now I have an application implementing the actual authentication. In essence:
- instance of AbstractAccountAuthenticator
- service to publish associated IBinder
- Activity to execute the login and store the account
- authenticator.xml and prefs.xml files And another app just as client that access the authentication. Both apps have the same UI to execute the following actions (using android.accounts.AccountManager):
- list the accounts of my type
- add a new account executing the authentication and storing it
- get the auth token
In the app with the authentication I can execute all actions without problem.
In the client app I can execute only first two actions:
- check if there are accounts of my type
- access the auth token stored from the authentication app
If the client app try to add a new account calling android.accounts.AccountManager#addAccount() the request is correctly delivered to the instance of AbstractAccountAuthenticator in the authentication app (passing the request through the service) but the Login Activity is not open for the following error:
2021-01-14 09:15:33.902 10413-10452/xxx.client1 W/Binder: Caught a RuntimeException from the binder stub implementation.
java.lang.SecurityException: Permission Denial: starting Intent { cmp=xxx.customaccount/xxx.ui.login.LoginActivity clip={text/plain {...}} (has extras) } from ProcessRecord{db30657 10413:xxx.client1/u0a155} (pid=10413, uid=10155) not exported from uid 10154
at android.os.Parcel.createExceptionOrNull(Parcel.java:2373)
at android.os.Parcel.createException(Parcel.java:2357)
at android.os.Parcel.readException(Parcel.java:2340)
at android.os.Parcel.readException(Parcel.java:2282)
at android.app.IActivityTaskManager$Stub$Proxy.startActivity(IActivityTaskManager.java:3696)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1723)
at android.app.Activity.startActivityForResult(Activity.java:5320)
at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:675)
at android.app.Activity.startActivityForResult(Activity.java:5278)
at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:662)
at android.app.Activity.startActivity(Activity.java:5664)
at android.app.Activity.startActivity(Activity.java:5617)
at android.accounts.AccountManager$AmsTask$Response.onResult(AccountManager.java:2330)
at android.accounts.IAccountManagerResponse$Stub.onTransact(IAccountManagerResponse.java:97)
at android.os.Binder.execTransactInternal(Binder.java:1159)
at android.os.Binder.execTransact(Binder.java:1123)
Caused by: android.os.RemoteException: Remote stack trace:
at com.android.server.wm.ActivityStackSupervisor.checkStartAnyActivityPermission(ActivityStackSupervisor.java:1032)
at com.android.server.wm.ActivityStarter.executeRequest(ActivityStarter.java:999)
at com.android.server.wm.ActivityStarter.execute(ActivityStarter.java:669)
at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1100)
at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1072)
Adding android:export=true for the Login activity the authentication starts but the storage doesn't work correcty (I don't think this is the correct direction because the authentication should be started in the authentication app to manage correctly the result of the activity). Any suggestion about how to solve this problem?
Thanks
gcast
Update: The suspect is that the sharing of tokens must be implemented in the apps (so in the client app and in the authenticaiton app) using other android components as bound services.