Show fullscreen “Access Request” dialog instead of notification when using getAuthToken(…)

前端 未结 3 1609
耶瑟儿~
耶瑟儿~ 2020-12-10 20:19

I built an AccountAuthenticator for a webservice that I\'d like to use in other applications with different signatures. I\'d like to instantly show the fullscreen access req

相关标签:
3条回答
  • 2020-12-10 20:41

    There isn't a good tutorial for this workflow but I was finally able to get this to work in my app. I am adding this answer for posterity for anyone else coming across this particular use case.

    Running as a Background Task

    manager.getAuthToken(account, "full", null, true, callback, new Handler());
    

    The above expects you to be running in some background task where you don't need to display UI right away. The java doc for this method explains this. Sadly, if you use a "false" flag you don't get a callback that the SecurityException occurred.

    Running in the Foreground

    manager.getAuthToken(account, "full", null, activity, callback, new Handler());
    

    This expects the app calling this method to share the same signing certificate of the authenticator. This is where I and many people are getting hung up. I tried a few versions of android from 4.0.1 onward to 5.0 and it seems to be intended behavior and not a bug in their code.

    The Solution

    Use a different means of getting the auth token. specifically confirm credentials of the account you need.

    mgr.confirmCredentials(account, null, activity, callback, null);
    

    By supporting Confirm Credentials you can send an intent to launch an AccountAuthenticatorActivity through the Authenticator and avoid the security exception. You have full control over the UI here so while normally you could request a new password for the account, you could instead show a page with a button to confirm that the account should be used in the calling application. Then, all you have to do is send the auth token in the AccountManagerCallback bundle going back to the calling app.

    Example Callback Method

    new AccountManagerCallback<Bundle>() {
    
        @Override
        public void run(AccountManagerFuture<Bundle> bundle) {
            boolean success = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
            if (success) {
                final String token = result.getString(AuthenticationHelper.ACCESS_TOKEN);
                //cache token somewhere local
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-10 20:44

    You are using wrong method. Have a look at documentation:
    - getAuthToken rising notification:
    - getAuthToken prompting the user for credentials if necessary

    Example of a method you are looking for:

    Bundle options = new Bundle();
    
    accountManager.getAccountManager().getAuthToken(account, SyncUtils.AUTH_TOKEN_TYPE, options, Accounts.this, new AccountManagerCallback<Bundle>() {
    
                @Override
                public void run(AccountManagerFuture<Bundle> future) {
    
                        Bundle bundle = bundle = future.getResult();
    
    
                        if(bundle == null)
                            return;
    
                        if (bundle.containsKey(AccountManager.KEY_INTENT)) {
    
                            Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);
                            intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK);
                            startActivityForResult(intent, SyncUtils.REQUEST_AUTHENTICATE);
    
                        } else if (bundle.containsKey(AccountManager.KEY_AUTHTOKEN)) {
    
                            ...
                            credential.setAccessToken(bundle.getString(AccountManager.KEY_AUTHTOKEN));
    
                            setUI();
    
                        }
    
                }
            }, null);
    
    0 讨论(0)
  • 2020-12-10 20:48

    This appears to be a bug (or security feature) in KitKat, preventing cross app token sharing. I recommend you implement token sharing using your own custom intents and security validation, rather than relying on Android's APIs.

    0 讨论(0)
提交回复
热议问题