use of android.accounts.AccountAuthenticatorResponse in project android_frameworks_base by ParanoidAndroid.
the class AccountManagerService method getAuthToken.
public void getAuthToken(IAccountManagerResponse response, final Account account, final String authTokenType, final boolean notifyOnAuthFailure, final boolean expectActivityLaunch, Bundle loginOptionsIn) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAuthToken: " + account + ", response " + response + ", authTokenType " + authTokenType + ", notifyOnAuthFailure " + notifyOnAuthFailure + ", expectActivityLaunch " + expectActivityLaunch + ", caller's uid " + Binder.getCallingUid() + ", pid " + Binder.getCallingPid());
}
if (response == null)
throw new IllegalArgumentException("response is null");
if (account == null)
throw new IllegalArgumentException("account is null");
if (authTokenType == null)
throw new IllegalArgumentException("authTokenType is null");
checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
final UserAccounts accounts = getUserAccountsForCaller();
final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
authenticatorInfo = mAuthenticatorCache.getServiceInfo(AuthenticatorDescription.newKey(account.type), accounts.userId);
final boolean customTokens = authenticatorInfo != null && authenticatorInfo.type.customTokens;
// restricted account.
if (!ArrayUtils.contains(getAccounts((String) null), account)) {
throw new IllegalArgumentException("no such account");
}
// skip the check if customTokens
final int callerUid = Binder.getCallingUid();
final boolean permissionGranted = customTokens || permissionIsGranted(account, authTokenType, callerUid);
final Bundle loginOptions = (loginOptionsIn == null) ? new Bundle() : loginOptionsIn;
// let authenticator know the identity of the caller
loginOptions.putInt(AccountManager.KEY_CALLER_UID, callerUid);
loginOptions.putInt(AccountManager.KEY_CALLER_PID, Binder.getCallingPid());
if (notifyOnAuthFailure) {
loginOptions.putBoolean(AccountManager.KEY_NOTIFY_ON_FAILURE, true);
}
long identityToken = clearCallingIdentity();
try {
// route of starting a Session
if (!customTokens && permissionGranted) {
String authToken = readAuthTokenInternal(accounts, account, authTokenType);
if (authToken != null) {
Bundle result = new Bundle();
result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
onResult(response, result);
return;
}
}
new Session(accounts, response, account.type, expectActivityLaunch, false) {
/* stripAuthTokenFromResult */
protected String toDebugString(long now) {
if (loginOptions != null)
loginOptions.keySet();
return super.toDebugString(now) + ", getAuthToken" + ", " + account + ", authTokenType " + authTokenType + ", loginOptions " + loginOptions + ", notifyOnAuthFailure " + notifyOnAuthFailure;
}
public void run() throws RemoteException {
// "grant permission" intent instead of the "getAuthToken" intent.
if (!permissionGranted) {
mAuthenticator.getAuthTokenLabel(this, authTokenType);
} else {
mAuthenticator.getAuthToken(this, account, authTokenType, loginOptions);
}
}
public void onResult(Bundle result) {
if (result != null) {
if (result.containsKey(AccountManager.KEY_AUTH_TOKEN_LABEL)) {
Intent intent = newGrantCredentialsPermissionIntent(account, callerUid, new AccountAuthenticatorResponse(this), authTokenType, result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL));
Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
onResult(bundle);
return;
}
String authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
if (authToken != null) {
String name = result.getString(AccountManager.KEY_ACCOUNT_NAME);
String type = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
if (TextUtils.isEmpty(type) || TextUtils.isEmpty(name)) {
onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "the type and name should not be empty");
return;
}
if (!customTokens) {
saveAuthTokenToDatabase(mAccounts, new Account(name, type), authTokenType, authToken);
}
}
Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
if (intent != null && notifyOnAuthFailure && !customTokens) {
doNotification(mAccounts, account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE), intent, accounts.userId);
}
}
super.onResult(result);
}
}.bind();
} finally {
restoreCallingIdentity(identityToken);
}
}
use of android.accounts.AccountAuthenticatorResponse in project platform_frameworks_base by android.
the class AccountManagerService method getAuthToken.
@Override
public void getAuthToken(IAccountManagerResponse response, final Account account, final String authTokenType, final boolean notifyOnAuthFailure, final boolean expectActivityLaunch, final Bundle loginOptions) {
Bundle.setDefusable(loginOptions, true);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAuthToken: " + account + ", response " + response + ", authTokenType " + authTokenType + ", notifyOnAuthFailure " + notifyOnAuthFailure + ", expectActivityLaunch " + expectActivityLaunch + ", caller's uid " + Binder.getCallingUid() + ", pid " + Binder.getCallingPid());
}
if (response == null)
throw new IllegalArgumentException("response is null");
try {
if (account == null) {
Slog.w(TAG, "getAuthToken called with null account");
response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, "account is null");
return;
}
if (authTokenType == null) {
Slog.w(TAG, "getAuthToken called with null authTokenType");
response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, "authTokenType is null");
return;
}
} catch (RemoteException e) {
Slog.w(TAG, "Failed to report error back to the client." + e);
return;
}
int userId = UserHandle.getCallingUserId();
long ident = Binder.clearCallingIdentity();
final UserAccounts accounts;
final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
try {
accounts = getUserAccounts(userId);
authenticatorInfo = mAuthenticatorCache.getServiceInfo(AuthenticatorDescription.newKey(account.type), accounts.userId);
} finally {
Binder.restoreCallingIdentity(ident);
}
final boolean customTokens = authenticatorInfo != null && authenticatorInfo.type.customTokens;
// skip the check if customTokens
final int callerUid = Binder.getCallingUid();
final boolean permissionGranted = customTokens || permissionIsGranted(account, authTokenType, callerUid, userId);
// Get the calling package. We will use it for the purpose of caching.
final String callerPkg = loginOptions.getString(AccountManager.KEY_ANDROID_PACKAGE_NAME);
List<String> callerOwnedPackageNames;
ident = Binder.clearCallingIdentity();
try {
callerOwnedPackageNames = Arrays.asList(mPackageManager.getPackagesForUid(callerUid));
} finally {
Binder.restoreCallingIdentity(ident);
}
if (callerPkg == null || !callerOwnedPackageNames.contains(callerPkg)) {
String msg = String.format("Uid %s is attempting to illegally masquerade as package %s!", callerUid, callerPkg);
throw new SecurityException(msg);
}
// let authenticator know the identity of the caller
loginOptions.putInt(AccountManager.KEY_CALLER_UID, callerUid);
loginOptions.putInt(AccountManager.KEY_CALLER_PID, Binder.getCallingPid());
if (notifyOnAuthFailure) {
loginOptions.putBoolean(AccountManager.KEY_NOTIFY_ON_FAILURE, true);
}
long identityToken = clearCallingIdentity();
try {
// Distill the caller's package signatures into a single digest.
final byte[] callerPkgSigDigest = calculatePackageSignatureDigest(callerPkg);
// route of starting a Session
if (!customTokens && permissionGranted) {
String authToken = readAuthTokenInternal(accounts, account, authTokenType);
if (authToken != null) {
Bundle result = new Bundle();
result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
onResult(response, result);
return;
}
}
if (customTokens) {
/*
* Look up tokens in the new cache only if the loginOptions don't have parameters
* outside of those expected to be injected by the AccountManager, e.g.
* ANDORID_PACKAGE_NAME.
*/
String token = readCachedTokenInternal(accounts, account, authTokenType, callerPkg, callerPkgSigDigest);
if (token != null) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAuthToken: cache hit ofr custom token authenticator.");
}
Bundle result = new Bundle();
result.putString(AccountManager.KEY_AUTHTOKEN, token);
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
onResult(response, result);
return;
}
}
new Session(accounts, response, account.type, expectActivityLaunch, false, /* stripAuthTokenFromResult */
account.name, false) {
/* authDetailsRequired */
@Override
protected String toDebugString(long now) {
if (loginOptions != null)
loginOptions.keySet();
return super.toDebugString(now) + ", getAuthToken" + ", " + account + ", authTokenType " + authTokenType + ", loginOptions " + loginOptions + ", notifyOnAuthFailure " + notifyOnAuthFailure;
}
@Override
public void run() throws RemoteException {
// "grant permission" intent instead of the "getAuthToken" intent.
if (!permissionGranted) {
mAuthenticator.getAuthTokenLabel(this, authTokenType);
} else {
mAuthenticator.getAuthToken(this, account, authTokenType, loginOptions);
}
}
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
if (result != null) {
if (result.containsKey(AccountManager.KEY_AUTH_TOKEN_LABEL)) {
Intent intent = newGrantCredentialsPermissionIntent(account, null, callerUid, new AccountAuthenticatorResponse(this), authTokenType, true);
Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
onResult(bundle);
return;
}
String authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
if (authToken != null) {
String name = result.getString(AccountManager.KEY_ACCOUNT_NAME);
String type = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
if (TextUtils.isEmpty(type) || TextUtils.isEmpty(name)) {
onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "the type and name should not be empty");
return;
}
Account resultAccount = new Account(name, type);
if (!customTokens) {
saveAuthTokenToDatabase(mAccounts, resultAccount, authTokenType, authToken);
}
long expiryMillis = result.getLong(AbstractAccountAuthenticator.KEY_CUSTOM_TOKEN_EXPIRY, 0L);
if (customTokens && expiryMillis > System.currentTimeMillis()) {
saveCachedToken(mAccounts, account, callerPkg, callerPkgSigDigest, authTokenType, authToken, expiryMillis);
}
}
Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
if (intent != null && notifyOnAuthFailure && !customTokens) {
/*
* Make sure that the supplied intent is owned by the authenticator
* giving it to the system. Otherwise a malicious authenticator could
* have users launching arbitrary activities by tricking users to
* interact with malicious notifications.
*/
checkKeyIntent(Binder.getCallingUid(), intent);
doNotification(mAccounts, account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE), intent, "android", accounts.userId);
}
}
super.onResult(result);
}
}.bind();
} finally {
restoreCallingIdentity(identityToken);
}
}
use of android.accounts.AccountAuthenticatorResponse in project platform_frameworks_base by android.
the class AccountManagerService method newRequestAccountAccessIntent.
private Intent newRequestAccountAccessIntent(Account account, String packageName, int uid, RemoteCallback callback) {
return newGrantCredentialsPermissionIntent(account, packageName, uid, new AccountAuthenticatorResponse(new IAccountAuthenticatorResponse.Stub() {
@Override
public void onResult(Bundle value) throws RemoteException {
handleAuthenticatorResponse(true);
}
@Override
public void onRequestContinued() {
/* ignore */
}
@Override
public void onError(int errorCode, String errorMessage) throws RemoteException {
handleAuthenticatorResponse(false);
}
private void handleAuthenticatorResponse(boolean accessGranted) throws RemoteException {
cancelNotification(getCredentialPermissionNotificationId(account, AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, uid), packageName, UserHandle.getUserHandleForUid(uid));
if (callback != null) {
Bundle result = new Bundle();
result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, accessGranted);
callback.sendResult(result);
}
}
}), AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, false);
}
use of android.accounts.AccountAuthenticatorResponse in project android_frameworks_base by DirtyUnicorns.
the class AccountManagerService method getAuthToken.
@Override
public void getAuthToken(IAccountManagerResponse response, final Account account, final String authTokenType, final boolean notifyOnAuthFailure, final boolean expectActivityLaunch, final Bundle loginOptions) {
Bundle.setDefusable(loginOptions, true);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAuthToken: " + account + ", response " + response + ", authTokenType " + authTokenType + ", notifyOnAuthFailure " + notifyOnAuthFailure + ", expectActivityLaunch " + expectActivityLaunch + ", caller's uid " + Binder.getCallingUid() + ", pid " + Binder.getCallingPid());
}
if (response == null)
throw new IllegalArgumentException("response is null");
try {
if (account == null) {
Slog.w(TAG, "getAuthToken called with null account");
response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, "account is null");
return;
}
if (authTokenType == null) {
Slog.w(TAG, "getAuthToken called with null authTokenType");
response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, "authTokenType is null");
return;
}
} catch (RemoteException e) {
Slog.w(TAG, "Failed to report error back to the client." + e);
return;
}
int userId = UserHandle.getCallingUserId();
long ident = Binder.clearCallingIdentity();
final UserAccounts accounts;
final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
try {
accounts = getUserAccounts(userId);
authenticatorInfo = mAuthenticatorCache.getServiceInfo(AuthenticatorDescription.newKey(account.type), accounts.userId);
} finally {
Binder.restoreCallingIdentity(ident);
}
final boolean customTokens = authenticatorInfo != null && authenticatorInfo.type.customTokens;
// skip the check if customTokens
final int callerUid = Binder.getCallingUid();
final boolean permissionGranted = customTokens || permissionIsGranted(account, authTokenType, callerUid, userId);
// Get the calling package. We will use it for the purpose of caching.
final String callerPkg = loginOptions.getString(AccountManager.KEY_ANDROID_PACKAGE_NAME);
List<String> callerOwnedPackageNames;
ident = Binder.clearCallingIdentity();
try {
callerOwnedPackageNames = Arrays.asList(mPackageManager.getPackagesForUid(callerUid));
} finally {
Binder.restoreCallingIdentity(ident);
}
if (callerPkg == null || !callerOwnedPackageNames.contains(callerPkg)) {
String msg = String.format("Uid %s is attempting to illegally masquerade as package %s!", callerUid, callerPkg);
throw new SecurityException(msg);
}
// let authenticator know the identity of the caller
loginOptions.putInt(AccountManager.KEY_CALLER_UID, callerUid);
loginOptions.putInt(AccountManager.KEY_CALLER_PID, Binder.getCallingPid());
if (notifyOnAuthFailure) {
loginOptions.putBoolean(AccountManager.KEY_NOTIFY_ON_FAILURE, true);
}
long identityToken = clearCallingIdentity();
try {
// Distill the caller's package signatures into a single digest.
final byte[] callerPkgSigDigest = calculatePackageSignatureDigest(callerPkg);
// route of starting a Session
if (!customTokens && permissionGranted) {
String authToken = readAuthTokenInternal(accounts, account, authTokenType);
if (authToken != null) {
Bundle result = new Bundle();
result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
onResult(response, result);
return;
}
}
if (customTokens) {
/*
* Look up tokens in the new cache only if the loginOptions don't have parameters
* outside of those expected to be injected by the AccountManager, e.g.
* ANDORID_PACKAGE_NAME.
*/
String token = readCachedTokenInternal(accounts, account, authTokenType, callerPkg, callerPkgSigDigest);
if (token != null) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAuthToken: cache hit ofr custom token authenticator.");
}
Bundle result = new Bundle();
result.putString(AccountManager.KEY_AUTHTOKEN, token);
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
onResult(response, result);
return;
}
}
new Session(accounts, response, account.type, expectActivityLaunch, false, /* stripAuthTokenFromResult */
account.name, false) {
/* authDetailsRequired */
@Override
protected String toDebugString(long now) {
if (loginOptions != null)
loginOptions.keySet();
return super.toDebugString(now) + ", getAuthToken" + ", " + account + ", authTokenType " + authTokenType + ", loginOptions " + loginOptions + ", notifyOnAuthFailure " + notifyOnAuthFailure;
}
@Override
public void run() throws RemoteException {
// "grant permission" intent instead of the "getAuthToken" intent.
if (!permissionGranted) {
mAuthenticator.getAuthTokenLabel(this, authTokenType);
} else {
mAuthenticator.getAuthToken(this, account, authTokenType, loginOptions);
}
}
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
if (result != null) {
if (result.containsKey(AccountManager.KEY_AUTH_TOKEN_LABEL)) {
Intent intent = newGrantCredentialsPermissionIntent(account, null, callerUid, new AccountAuthenticatorResponse(this), authTokenType, true);
Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
onResult(bundle);
return;
}
String authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
if (authToken != null) {
String name = result.getString(AccountManager.KEY_ACCOUNT_NAME);
String type = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
if (TextUtils.isEmpty(type) || TextUtils.isEmpty(name)) {
onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "the type and name should not be empty");
return;
}
Account resultAccount = new Account(name, type);
if (!customTokens) {
saveAuthTokenToDatabase(mAccounts, resultAccount, authTokenType, authToken);
}
long expiryMillis = result.getLong(AbstractAccountAuthenticator.KEY_CUSTOM_TOKEN_EXPIRY, 0L);
if (customTokens && expiryMillis > System.currentTimeMillis()) {
saveCachedToken(mAccounts, account, callerPkg, callerPkgSigDigest, authTokenType, authToken, expiryMillis);
}
}
Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
if (intent != null && notifyOnAuthFailure && !customTokens) {
/*
* Make sure that the supplied intent is owned by the authenticator
* giving it to the system. Otherwise a malicious authenticator could
* have users launching arbitrary activities by tricking users to
* interact with malicious notifications.
*/
checkKeyIntent(Binder.getCallingUid(), intent);
doNotification(mAccounts, account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE), intent, "android", accounts.userId);
}
}
super.onResult(result);
}
}.bind();
} finally {
restoreCallingIdentity(identityToken);
}
}
use of android.accounts.AccountAuthenticatorResponse in project android_frameworks_base by AOSPA.
the class AccountManagerService method newRequestAccountAccessIntent.
private Intent newRequestAccountAccessIntent(Account account, String packageName, int uid, RemoteCallback callback) {
return newGrantCredentialsPermissionIntent(account, packageName, uid, new AccountAuthenticatorResponse(new IAccountAuthenticatorResponse.Stub() {
@Override
public void onResult(Bundle value) throws RemoteException {
handleAuthenticatorResponse(true);
}
@Override
public void onRequestContinued() {
/* ignore */
}
@Override
public void onError(int errorCode, String errorMessage) throws RemoteException {
handleAuthenticatorResponse(false);
}
private void handleAuthenticatorResponse(boolean accessGranted) throws RemoteException {
cancelNotification(getCredentialPermissionNotificationId(account, AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, uid), packageName, UserHandle.getUserHandleForUid(uid));
if (callback != null) {
Bundle result = new Bundle();
result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, accessGranted);
callback.sendResult(result);
}
}
}), AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, false);
}
Aggregations