package com.lnikkila.oidc.security; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AccountManagerCallback; import android.accounts.AccountManagerFuture; import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; import android.content.Context; import android.os.Build; import android.os.Bundle; import java.io.IOException; /** * Created by Camilo Montes on 18/01/2016. <br/> * Copyright LaPoste <br/> */ public class AccountSensitiveDataStorageUtils { private final static boolean SHOW_NOTIF_ON_AUTHFAILURE = true; private SensitiveDataUtils dataEncUtils; public AccountSensitiveDataStorageUtils(Context context) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { dataEncUtils = new SensitiveDataPreApi23(context); } else { dataEncUtils = new SensitiveDataPostApi23(context); } } /** * Get the stored data from a secure store, decrypting the data if needed. * @return The data store on the secure storage. */ public String retrieveStringData(AccountManager accountManager, Account account, String tokenType, AccountManagerCallback<Bundle> callback) throws UserNotAuthenticatedWrapperException, AuthenticatorException, OperationCanceledException, IOException { String data = null; // Try retrieving an access token from the account manager. The boolean #SHOW_NOTIF_ON_AUTHFAILURE in the invocation // tells Android to show a notification if the token can't be retrieved. When the // notification is selected, it will launch the intent for re-authorisation. You could // launch it automatically here if you wanted to by grabbing the intent from the bundle. AccountManagerFuture<Bundle> futureManager; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { //noinspection deprecation futureManager = accountManager.getAuthToken( account, tokenType, SHOW_NOTIF_ON_AUTHFAILURE, callback, null); } else { futureManager = accountManager.getAuthToken( account, tokenType, null, SHOW_NOTIF_ON_AUTHFAILURE, callback, null); } String encryptedToken = futureManager.getResult().getString(AccountManager.KEY_AUTHTOKEN); if (encryptedToken != null) { data = dataEncUtils.decrypt(encryptedToken); } return data; } /** * Store the given serialized data onto a secure store, encrypting the data if needed. * @param data The data to store securely * @return true if the data was store, false otherwise. */ public boolean storeStringData(AccountManager accountManager, Account account, String tokenType, String data) throws UserNotAuthenticatedWrapperException { accountManager.setAuthToken(account, tokenType, dataEncUtils.encrypt(data)); return true; } public void invalidateStringData(AccountManager accountManager, Account account, String data) throws UserNotAuthenticatedWrapperException { accountManager.invalidateAuthToken(account.type, dataEncUtils.encrypt(data)); } }