Permalink
Browse files

Add OAuth support

Closes issue #75 and issue #184
  • Loading branch information...
1 parent ba9d173 commit 13c6a7ec155b5905aeb6e110762d8388376da17f @TrevorBasinger TrevorBasinger committed with kevinsawicki Oct 5, 2012
View
@@ -15,3 +15,4 @@ gen-external-apklibs
.idea
*.iml
.DS_Store
+*.swp
@@ -15,6 +15,7 @@
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
+ <uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<supports-screens
@@ -338,4 +339,4 @@
android:exported="false" />
</application>
-</manifest>
+</manifest>
@@ -40,6 +40,9 @@
import org.eclipse.egit.github.core.service.IssueService;
import org.eclipse.egit.github.core.service.PullRequestService;
+import static com.github.mobile.accounts.AccountConstants.ACCOUNT_NAME;
+import static com.github.mobile.accounts.AccountConstants.APP_URL;
+
/**
* Main module provide services and clients
*/
@@ -31,6 +31,7 @@
import org.eclipse.egit.github.core.service.LabelService;
import org.eclipse.egit.github.core.service.MilestoneService;
import org.eclipse.egit.github.core.service.OrganizationService;
+import org.eclipse.egit.github.core.service.OAuthService;
import org.eclipse.egit.github.core.service.PullRequestService;
import org.eclipse.egit.github.core.service.RepositoryService;
import org.eclipse.egit.github.core.service.UserService;
@@ -19,21 +19,34 @@
import static android.accounts.AccountManager.KEY_BOOLEAN_RESULT;
import static android.accounts.AccountManager.KEY_INTENT;
import static com.github.mobile.accounts.AccountConstants.ACCOUNT_TYPE;
+import static com.github.mobile.accounts.AccountConstants.ACCOUNT_NAME;
+import static com.github.mobile.accounts.AccountConstants.APP_URL;
import static com.github.mobile.accounts.LoginActivity.PARAM_AUTHTOKEN_TYPE;
import static com.github.mobile.accounts.LoginActivity.PARAM_USERNAME;
+import com.github.mobile.DefaultClient;
import android.accounts.AbstractAccountAuthenticator;
import android.accounts.Account;
+import android.accounts.AccountManager;
import android.accounts.AccountAuthenticatorResponse;
import android.accounts.NetworkErrorException;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
+import android.util.Log;
+
+import org.eclipse.egit.github.core.service.OAuthService;
+import org.eclipse.egit.github.core.Authorization;
+
+import java.lang.Thread;
+import java.util.List;
class AccountAuthenticator extends AbstractAccountAuthenticator {
private Context context;
+ private final static String TAG = "GitHubAccountAuthenticator";
+
public AccountAuthenticator(final Context context) {
super(context);
@@ -75,7 +88,55 @@ public Bundle editProperties(AccountAuthenticatorResponse response,
public Bundle getAuthToken(AccountAuthenticatorResponse response,
Account account, String authTokenType, Bundle options)
throws NetworkErrorException {
- return null;
+
+ final Bundle bundle = new Bundle();
+
+ if(!authTokenType.equals(ACCOUNT_TYPE)) return bundle;
+
+ AccountManager am = AccountManager.get(context);
+ String username = account.name;
+ String password = am.getPassword(account);
+
+ String authToken = null;
+ DefaultClient client = new DefaultClient();
+ client.setCredentials(username, password);
+
+ OAuthService oAuthService = new OAuthService(client);
+
+ // Get authorizations for app if they exist
+ try {
+ List<Authorization> auths = oAuthService.getAuthorizations();
+ for(Authorization auth : auths)
+ if(auth.getApp().getName().equals(ACCOUNT_NAME))
+ authToken = auth.getToken();
+
+ // Setup authorization for app if others didn't exist.
+ if(TextUtils.isEmpty(authToken)) {
+ Authorization auth = oAuthService.createAuthorization(
+ new Authorization().setNote(ACCOUNT_NAME).setUrl(APP_URL)
+ );
+ if(auth != null) authToken = auth.getToken();
+ }
+
+ // If couldn't get authToken
+ if(TextUtils.isEmpty(authToken)) {
+ final Intent intent = new Intent(context, LoginActivity.class);
+ intent.putExtra(PARAM_AUTHTOKEN_TYPE, ACCOUNT_TYPE);
+ intent.putExtra(KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
+ bundle.putParcelable(KEY_INTENT, intent);
+ return bundle;
+ }
+
+ // Assemble and return bundle
+ bundle.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
+ bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);
+ bundle.putString(AccountManager.KEY_AUTHTOKEN, authToken);
+
+ // Clear password from account
+ am.clearPassword(account);
+ return bundle;
+ } catch ( Exception e ) { Log.e(TAG, e.getMessage()); }
+ return bundle;
}
@Override
@@ -16,6 +16,7 @@
package com.github.mobile.accounts;
import static android.util.Log.DEBUG;
+import android.text.TextUtils;
import android.util.Log;
import com.github.mobile.DefaultClient;
@@ -54,7 +55,10 @@ protected HttpURLConnection configureRequest(final HttpURLConnection request) {
Log.d(TAG, "Authenticating using " + account);
// Credentials setting must come before super call
- setCredentials(account.username, account.password);
+ if(!TextUtils.isEmpty(account.authToken)) // Use token if it exists
+ setOAuth2Token(account.authToken);
+ else
+ setCredentials(account.username, account.password);
return super.configureRequest(request);
}
@@ -34,4 +34,9 @@
* Provider authority
*/
String PROVIDER_AUTHORITY = "com.github.sync";
+
+ /**
+ * Application URL
+ */
+ String APP_URL = "https://github.com/github/android";
}
@@ -17,15 +17,27 @@
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.os.Bundle;
+import android.util.Log;
import com.google.inject.AbstractModule;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.OutOfScopeException;
+import java.io.IOException;
+
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import static com.github.mobile.accounts.AccountConstants.ACCOUNT_TYPE;
+
/**
* Custom scope that makes an authenticated GitHub account available by
* enforcing that the user is logged in before proceeding.
@@ -35,6 +47,8 @@
private static final Key<GitHubAccount> GITHUB_ACCOUNT_KEY = Key
.get(GitHubAccount.class);
+ private static final String TAG = "GitHubAccountScope";
+
/**
* Create new module
*
@@ -66,8 +80,22 @@ public void configure() {
*/
public void enterWith(final Account account,
final AccountManager accountManager) {
+ AccountManagerFuture future =
+ accountManager.getAuthToken(account, ACCOUNT_TYPE, null, true, null, null);
+
+ Bundle result = null;
+ String authToken = null;
+ try {
+ result = (Bundle) future.getResult();
+ authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
+ }
+ catch (AuthenticatorException ae) { Log.e(TAG, ae.getMessage()); } // Authenticator failed to respond
+ catch (OperationCanceledException oce) { Log.e(TAG, oce.getMessage()); } // User canceled operation
+ catch (IOException ioe) { Log.e(TAG, ioe.getMessage()); } // Possible network issues
+
enterWith(new GitHubAccount(account.name,
- accountManager.getPassword(account)));
+ accountManager.getPassword(account),
+ authToken));
}
/**
@@ -108,4 +136,4 @@ public void exit() {
}
return scopeMap;
}
-}
+}
@@ -15,6 +15,8 @@
*/
package com.github.mobile.accounts;
+import android.util.Log;
+
/**
* GitHub account model
*/
@@ -29,16 +31,23 @@
* Account password
*/
public final String password;
+
+ /**
+ * Account password
+ */
+ public final String authToken;
/**
* Create account with username and password
*
* @param username
* @param password
+ * @param authToken
*/
- public GitHubAccount(String username, String password) {
+ public GitHubAccount(String username, String password, String authToken) {
this.username = username;
this.password = password;
+ this.authToken = authToken;
}
@Override
@@ -31,7 +31,7 @@
* Test sorting of users that match login
*/
public void testLoginMatch() {
- GitHubAccount account = new GitHubAccount("m", "n");
+ GitHubAccount account = new GitHubAccount("m", "n", "a");
UserComparator comparator = new UserComparator(account);
assertTrue(comparator.compare(new User().setLogin("m"),
@@ -52,7 +52,7 @@ public void testLoginMatch() {
* Test sorting of users that don't match login
*/
public void testNoLoginMatch() {
- GitHubAccount account = new GitHubAccount("m", "n");
+ GitHubAccount account = new GitHubAccount("m", "n", "a");
UserComparator comparator = new UserComparator(account);
assertTrue(comparator.compare(new User().setLogin("a"),

0 comments on commit 13c6a7e

Please sign in to comment.