Loading src/main/java/com/nextcloud/android/sso/AccountImporter.java +30 −1 Original line number Diff line number Diff line Loading @@ -7,10 +7,13 @@ import android.accounts.OperationCanceledException; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.annotation.RequiresApi; import android.util.Log; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotInstalledException; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotSupportedException; Loading Loading @@ -62,6 +65,10 @@ public class AccountImporter { public static void PickNewAccount(android.support.v4.app.Fragment fragment) throws NextcloudFilesAppNotInstalledException { if(AppInstalledOrNot(fragment.getContext(), "com.nextcloud.client")) { // Clear all tokens first to prevent some caching issues.. ClearAllAuthTokens(fragment.getContext()); Intent intent = AccountManager.newChooseAccountIntent(null, null, new String[]{"nextcloud"}, true, null, null, null, null); fragment.startActivityForResult(intent, CHOOSE_ACCOUNT_SSO); Loading Loading @@ -117,8 +124,28 @@ public class AccountImporter { return result; } public static void ClearAllAuthTokens(Context context) { SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context); for(String key : mPrefs.getAll().keySet()) { if(key.startsWith(PREF_ACCOUNT_STRING)) { mPrefs.edit().remove(key).apply(); } } } // Get the AuthToken (Password) for a selected account public static SingleSignOnAccount GetAuthToken(Context context, Account account) throws AuthenticatorException, OperationCanceledException, IOException, NextcloudFilesAppNotSupportedException { SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context); String prefKey = PREF_ACCOUNT_STRING + account.name; if(mPrefs.contains(prefKey)) { try { return SingleSignOnAccount.fromString(mPrefs.getString(prefKey, null)); } catch (ClassNotFoundException e) { Log.e(TAG, "This should never happen!"); e.printStackTrace(); } } final AccountManager accMgr = AccountManager.get(context); Bundle options = new Bundle(); accMgr.invalidateAuthToken(account.type, AUTH_TOKEN); Loading Loading @@ -147,7 +174,9 @@ public class AccountImporter { String token = future.getString(Constants.SSO_TOKEN); String server_url = future.getString(Constants.SSO_SERVER_URL); return new SingleSignOnAccount(account.name, username, token, server_url); SingleSignOnAccount ssoAccount = new SingleSignOnAccount(account.name, username, token, server_url); mPrefs.edit().putString(prefKey, SingleSignOnAccount.toString(ssoAccount)).apply(); return ssoAccount; } Loading src/main/java/com/nextcloud/android/sso/aidl/NextcloudRequest.java +1 −25 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ import java.util.Map; public class NextcloudRequest implements Serializable { private static final long serialVersionUID = 215521212534239L; //assign a long value private static final long serialVersionUID = 215521212534240L; //assign a long value private String method; private Map<String, List<String>> header = new HashMap<>(); Loading Loading @@ -81,11 +81,6 @@ public class NextcloudRequest implements Serializable { return this; } public Builder setPackageName(String packageName) { ncr.packageName = packageName; return this; } public Builder setAccountName(String accountName) { ncr.accountName = accountName; return this; Loading Loading @@ -149,23 +144,4 @@ public class NextcloudRequest implements Serializable { public boolean isFollowRedirects() { return this.followRedirects; } public boolean validateToken(String token) { // As discussed with Lukas R. at the Nextcloud Conf 2018, always compare whole strings // and don't exit prematurely if the string does not match anymore to prevent timing-attacks return isEqual(this.token.getBytes(), token.getBytes()); } // Taken from http://codahale.com/a-lesson-in-timing-attacks/ private static boolean isEqual(byte[] a, byte[] b) { if (a.length != b.length) { return false; } int result = 0; for (int i = 0; i < a.length; i++) { result |= a[i] ^ b[i]; } return result == 0; } } src/main/java/com/nextcloud/android/sso/api/NextcloudAPI.java +0 −5 Original line number Diff line number Diff line Loading @@ -289,11 +289,6 @@ public class NextcloudAPI { public static <T> T deserializeObjectAndCloseStream(InputStream is) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(is); T result = (T) ois.readObject(); Loading src/main/java/com/nextcloud/android/sso/model/SingleSignOnAccount.java +33 −1 Original line number Diff line number Diff line package com.nextcloud.android.sso.model; import android.util.Base64; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * Nextcloud SingleSignOn * Loading @@ -20,7 +29,9 @@ package com.nextcloud.android.sso.model; */ public class SingleSignOnAccount { public class SingleSignOnAccount implements Serializable { private static final long serialVersionUID = 21523240203234240L; //assign a long value public SingleSignOnAccount(String name, String username, String token, String url) { this.name = name; Loading @@ -34,4 +45,25 @@ public class SingleSignOnAccount { public String token; public String url; /** Read the object from Base64 string. */ public static SingleSignOnAccount fromString(String s) throws IOException, ClassNotFoundException { byte [] data = Base64.decode(s, Base64.DEFAULT); ObjectInputStream ois = new ObjectInputStream( new ByteArrayInputStream( data ) ); SingleSignOnAccount o = (SingleSignOnAccount) ois.readObject(); ois.close(); return o; } /** Write the object to a Base64 string. * @param o*/ public static String toString(SingleSignOnAccount o) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream( baos ); oos.writeObject( o ); oos.close(); return new String(Base64.encode(baos.toByteArray(), Base64.DEFAULT)); } } Loading
src/main/java/com/nextcloud/android/sso/AccountImporter.java +30 −1 Original line number Diff line number Diff line Loading @@ -7,10 +7,13 @@ import android.accounts.OperationCanceledException; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.annotation.RequiresApi; import android.util.Log; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotInstalledException; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotSupportedException; Loading Loading @@ -62,6 +65,10 @@ public class AccountImporter { public static void PickNewAccount(android.support.v4.app.Fragment fragment) throws NextcloudFilesAppNotInstalledException { if(AppInstalledOrNot(fragment.getContext(), "com.nextcloud.client")) { // Clear all tokens first to prevent some caching issues.. ClearAllAuthTokens(fragment.getContext()); Intent intent = AccountManager.newChooseAccountIntent(null, null, new String[]{"nextcloud"}, true, null, null, null, null); fragment.startActivityForResult(intent, CHOOSE_ACCOUNT_SSO); Loading Loading @@ -117,8 +124,28 @@ public class AccountImporter { return result; } public static void ClearAllAuthTokens(Context context) { SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context); for(String key : mPrefs.getAll().keySet()) { if(key.startsWith(PREF_ACCOUNT_STRING)) { mPrefs.edit().remove(key).apply(); } } } // Get the AuthToken (Password) for a selected account public static SingleSignOnAccount GetAuthToken(Context context, Account account) throws AuthenticatorException, OperationCanceledException, IOException, NextcloudFilesAppNotSupportedException { SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context); String prefKey = PREF_ACCOUNT_STRING + account.name; if(mPrefs.contains(prefKey)) { try { return SingleSignOnAccount.fromString(mPrefs.getString(prefKey, null)); } catch (ClassNotFoundException e) { Log.e(TAG, "This should never happen!"); e.printStackTrace(); } } final AccountManager accMgr = AccountManager.get(context); Bundle options = new Bundle(); accMgr.invalidateAuthToken(account.type, AUTH_TOKEN); Loading Loading @@ -147,7 +174,9 @@ public class AccountImporter { String token = future.getString(Constants.SSO_TOKEN); String server_url = future.getString(Constants.SSO_SERVER_URL); return new SingleSignOnAccount(account.name, username, token, server_url); SingleSignOnAccount ssoAccount = new SingleSignOnAccount(account.name, username, token, server_url); mPrefs.edit().putString(prefKey, SingleSignOnAccount.toString(ssoAccount)).apply(); return ssoAccount; } Loading
src/main/java/com/nextcloud/android/sso/aidl/NextcloudRequest.java +1 −25 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ import java.util.Map; public class NextcloudRequest implements Serializable { private static final long serialVersionUID = 215521212534239L; //assign a long value private static final long serialVersionUID = 215521212534240L; //assign a long value private String method; private Map<String, List<String>> header = new HashMap<>(); Loading Loading @@ -81,11 +81,6 @@ public class NextcloudRequest implements Serializable { return this; } public Builder setPackageName(String packageName) { ncr.packageName = packageName; return this; } public Builder setAccountName(String accountName) { ncr.accountName = accountName; return this; Loading Loading @@ -149,23 +144,4 @@ public class NextcloudRequest implements Serializable { public boolean isFollowRedirects() { return this.followRedirects; } public boolean validateToken(String token) { // As discussed with Lukas R. at the Nextcloud Conf 2018, always compare whole strings // and don't exit prematurely if the string does not match anymore to prevent timing-attacks return isEqual(this.token.getBytes(), token.getBytes()); } // Taken from http://codahale.com/a-lesson-in-timing-attacks/ private static boolean isEqual(byte[] a, byte[] b) { if (a.length != b.length) { return false; } int result = 0; for (int i = 0; i < a.length; i++) { result |= a[i] ^ b[i]; } return result == 0; } }
src/main/java/com/nextcloud/android/sso/api/NextcloudAPI.java +0 −5 Original line number Diff line number Diff line Loading @@ -289,11 +289,6 @@ public class NextcloudAPI { public static <T> T deserializeObjectAndCloseStream(InputStream is) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(is); T result = (T) ois.readObject(); Loading
src/main/java/com/nextcloud/android/sso/model/SingleSignOnAccount.java +33 −1 Original line number Diff line number Diff line package com.nextcloud.android.sso.model; import android.util.Base64; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * Nextcloud SingleSignOn * Loading @@ -20,7 +29,9 @@ package com.nextcloud.android.sso.model; */ public class SingleSignOnAccount { public class SingleSignOnAccount implements Serializable { private static final long serialVersionUID = 21523240203234240L; //assign a long value public SingleSignOnAccount(String name, String username, String token, String url) { this.name = name; Loading @@ -34,4 +45,25 @@ public class SingleSignOnAccount { public String token; public String url; /** Read the object from Base64 string. */ public static SingleSignOnAccount fromString(String s) throws IOException, ClassNotFoundException { byte [] data = Base64.decode(s, Base64.DEFAULT); ObjectInputStream ois = new ObjectInputStream( new ByteArrayInputStream( data ) ); SingleSignOnAccount o = (SingleSignOnAccount) ois.readObject(); ois.close(); return o; } /** Write the object to a Base64 string. * @param o*/ public static String toString(SingleSignOnAccount o) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream( baos ); oos.writeObject( o ); oos.close(); return new String(Base64.encode(baos.toByteArray(), Base64.DEFAULT)); } }