Back to project page Android-Activity-Tracker-for-Dynamics-CRM.
The source code is released under:
MIT License
If you think the Android project Android-Activity-Tracker-for-Dynamics-CRM listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
// Copyright Microsoft Open Technologies, Inc. ///*from w w w . j av a2s .c o m*/ // All Rights Reserved // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS // OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION // ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A // PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT. // // See the Apache License, Version 2.0 for the specific language // governing permissions and limitations under the License. package com.microsoft.aad.adal; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import javax.crypto.NoSuchPaddingException; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.pm.PackageManager.NameNotFoundException; import com.google.gson.Gson; /** * Store/Retrieve TokenCacheItem from private SharedPreferences. * SharedPreferences saves items when it is committed in an atomic operation. * One more retry is attempted in case there is a lock in commit. */ public class DefaultTokenCacheStore implements ITokenCacheStore, ITokenStoreQuery { private static final long serialVersionUID = 1L; private static final String SHARED_PREFERENCE_NAME = "com.microsoft.aad.adal.cache"; private static final String TAG = "DefaultTokenCacheStore"; SharedPreferences mPrefs; private Context mContext; private Gson mGson = new Gson(); private static StorageHelper sHelper; private static Object sLock = new Object(); /** * @param context {@link Context} * @throws NoSuchAlgorithmException * @throws NoSuchPaddingException */ public DefaultTokenCacheStore(Context context) throws NoSuchAlgorithmException, NoSuchPaddingException { mContext = context; if (context != null) { if (!StringExtensions.IsNullOrBlank(AuthenticationSettings.INSTANCE .getSharedPrefPackageName())) { try { // Context is created from specified packagename in order to // use same file. Reading private data is only allowed if apps specify same // sharedUserId. Android OS will assign same UID, if they // are signed with same certificates. mContext = context.createPackageContext( AuthenticationSettings.INSTANCE.getSharedPrefPackageName(), Context.MODE_PRIVATE); } catch (NameNotFoundException e) { throw new IllegalArgumentException("Package name:" + AuthenticationSettings.INSTANCE.getSharedPrefPackageName() + " is not found"); } } mPrefs = mContext.getSharedPreferences(SHARED_PREFERENCE_NAME, Activity.MODE_PRIVATE); } else { throw new IllegalArgumentException("Context is null"); } synchronized (sLock) { if (sHelper == null) { Logger.v(TAG, "Started to initialize storage helper"); sHelper = new StorageHelper(mContext); Logger.v(TAG, "Finished to initialize storage helper"); } } } private String encrypt(String value) { try { return sHelper.encrypt(value); } catch (Exception e) { Logger.e(TAG, "Encryption failure", "", ADALError.ENCRYPTION_FAILED, e); } return null; } private String decrypt(String value) { try { return sHelper.decrypt(value); } catch (Exception e) { Logger.e(TAG, "Decryption failure", "", ADALError.ENCRYPTION_FAILED, e); if (!StringExtensions.IsNullOrBlank(value)) { Logger.v(TAG, String.format("Decryption error for key: '%s'. Item will be removed", value)); removeItem(value); Logger.v(TAG, String.format("Item removed for key: '%s'", value)); } } return null; } @Override public TokenCacheItem getItem(String key) { argumentCheck(); if (key == null) { throw new IllegalArgumentException("key"); } if (mPrefs.contains(key)) { String json = mPrefs.getString(key, ""); String decrypted = decrypt(json); if (decrypted != null) { return mGson.fromJson(decrypted, TokenCacheItem.class); } } return null; } @Override public void removeItem(String key) { argumentCheck(); if (key == null) { throw new IllegalArgumentException("key"); } if (mPrefs.contains(key)) { Editor prefsEditor = mPrefs.edit(); prefsEditor.remove(key); // apply will do Async disk write operation. prefsEditor.apply(); } } @Override public void setItem(String key, TokenCacheItem item) { argumentCheck(); if (key == null) { throw new IllegalArgumentException("key"); } if (item == null) { throw new IllegalArgumentException("item"); } String json = mGson.toJson(item); String encrypted = encrypt(json); if (encrypted != null) { Editor prefsEditor = mPrefs.edit(); prefsEditor.putString(key, encrypted); // apply will do Async disk write operation. prefsEditor.apply(); } else { Logger.e(TAG, "Encrypted output is null", "", ADALError.ENCRYPTION_FAILED); } } @Override public void removeAll() { argumentCheck(); Editor prefsEditor = mPrefs.edit(); prefsEditor.clear(); // apply will do Async disk write operation. prefsEditor.apply(); } // Extra helper methods can be implemented here for queries /** * User can query over iterator values. */ @Override public Iterator<TokenCacheItem> getAll() { argumentCheck(); @SuppressWarnings("unchecked") Map<String, String> results = (Map<String, String>)mPrefs.getAll(); Iterator<String> values = results.values().iterator(); // create objects ArrayList<TokenCacheItem> tokens = new ArrayList<TokenCacheItem>(results.values().size()); while (values.hasNext()) { String json = values.next(); String decrypted = decrypt(json); if (decrypted != null) { TokenCacheItem cacheItem = mGson.fromJson(decrypted, TokenCacheItem.class); tokens.add(cacheItem); } } return tokens.iterator(); } /** * Unique users with tokens. * * @return unique users */ @Override public HashSet<String> getUniqueUsersWithTokenCache() { Iterator<TokenCacheItem> results = this.getAll(); HashSet<String> users = new HashSet<String>(); while (results.hasNext()) { TokenCacheItem item = results.next(); if (item.getUserInfo() != null && !users.contains(item.getUserInfo().getUserId())) { users.add(item.getUserInfo().getUserId()); } } return users; } /** * Tokens for resource. * * @param resource Resource identifier * @return list of {@link TokenCacheItem} */ @Override public ArrayList<TokenCacheItem> getTokensForResource(String resource) { Iterator<TokenCacheItem> results = this.getAll(); ArrayList<TokenCacheItem> tokenItems = new ArrayList<TokenCacheItem>(); while (results.hasNext()) { TokenCacheItem item = results.next(); if (item.getResource().equals(resource)) { tokenItems.add(item); } } return tokenItems; } /** * Get tokens for user. * * @param userid Userid * @return list of {@link TokenCacheItem} */ @Override public ArrayList<TokenCacheItem> getTokensForUser(String userid) { Iterator<TokenCacheItem> results = this.getAll(); ArrayList<TokenCacheItem> tokenItems = new ArrayList<TokenCacheItem>(); while (results.hasNext()) { TokenCacheItem item = results.next(); if (item.getUserInfo() != null && item.getUserInfo().getUserId().equalsIgnoreCase(userid)) { tokenItems.add(item); } } return tokenItems; } /** * Clear tokens for user without additional retry. * * @param userid UserId */ @Override public void clearTokensForUser(String userid) { ArrayList<TokenCacheItem> results = this.getTokensForUser(userid); for (TokenCacheItem item : results) { if (item.getUserInfo() != null && item.getUserInfo().getUserId().equalsIgnoreCase(userid)) { this.removeItem(CacheKey.createCacheKey(item)); } } } /** * Get tokens about to expire. * * @return list of {@link TokenCacheItem} */ @Override public ArrayList<TokenCacheItem> getTokensAboutToExpire() { Iterator<TokenCacheItem> results = this.getAll(); ArrayList<TokenCacheItem> tokenItems = new ArrayList<TokenCacheItem>(); while (results.hasNext()) { TokenCacheItem item = results.next(); if (isAboutToExpire(item.getExpiresOn())) { tokenItems.add(item); } } return tokenItems; } private void argumentCheck() { if (mContext == null) { throw new AuthenticationException(ADALError.DEVELOPER_CONTEXT_IS_NOT_PROVIDED); } if (mPrefs == null) { throw new AuthenticationException(ADALError.DEVICE_SHARED_PREF_IS_NOT_AVAILABLE); } } private boolean isAboutToExpire(Date expires) { Date validity = getTokenValidityTime().getTime(); if (expires != null && expires.before(validity)) { return true; } return false; } private static final int TOKEN_VALIDITY_WINDOW = 10; private static Calendar getTokenValidityTime() { Calendar timeAhead = Calendar.getInstance(); timeAhead.add(Calendar.SECOND, TOKEN_VALIDITY_WINDOW); return timeAhead; } @Override public boolean contains(String key) { argumentCheck(); if (key == null) { throw new IllegalArgumentException("key"); } return mPrefs.contains(key); } }