Last active
May 11, 2023 20:00
-
-
Save TomTasche/5665497 to your computer and use it in GitHub Desktop.
OAuth flow using the AccountManager on Android
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- ... --> | |
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> | |
<uses-permission android:name="android.permission.INTERNET" /> | |
<uses-permission android:name="android.permission.USE_CREDENTIALS" /> | |
<!-- ... --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.accounts.Account; | |
import android.accounts.AccountManager; | |
import android.accounts.AccountManagerCallback; | |
import android.accounts.AccountManagerFuture; | |
import android.app.Activity; | |
import android.content.Intent; | |
import android.os.Bundle; | |
public class AuthActivity extends Activity { | |
private static final int AUTHORIZATION_CODE = 1993; | |
private static final int ACCOUNT_CODE = 1601; | |
private AuthPreferences authPreferences; | |
private AccountManager accountManager; | |
/** | |
* change this depending on the scope needed for the things you do in | |
* doCoolAuthenticatedStuff() | |
*/ | |
private final String SCOPE = "https://www.googleapis.com/auth/googletalk"; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
accountManager = AccountManager.get(this); | |
authPreferences = new AuthPreferences(this); | |
if (authPreferences.getUser() != null | |
&& authPreferences.getToken() != null) { | |
doCoolAuthenticatedStuff(); | |
} else { | |
chooseAccount(); | |
} | |
} | |
private void doCoolAuthenticatedStuff() { | |
// TODO: insert cool stuff with authPreferences.getToken() | |
Log.e("AuthApp", authPreferences.getToken()); | |
} | |
private void chooseAccount() { | |
// use https://github.com/frakbot/Android-AccountChooser for | |
// compatibility with older devices | |
Intent intent = AccountManager.newChooseAccountIntent(null, null, | |
new String[] { "com.google" }, false, null, null, null, null); | |
startActivityForResult(intent, ACCOUNT_CODE); | |
} | |
private void requestToken() { | |
Account userAccount = null; | |
String user = authPreferences.getUser(); | |
for (Account account : accountManager.getAccountsByType("com.google")) { | |
if (account.name.equals(user)) { | |
userAccount = account; | |
break; | |
} | |
} | |
accountManager.getAuthToken(userAccount, "oauth2:" + SCOPE, null, this, | |
new OnTokenAcquired(), null); | |
} | |
/** | |
* call this method if your token expired, or you want to request a new | |
* token for whatever reason. call requestToken() again afterwards in order | |
* to get a new token. | |
*/ | |
private void invalidateToken() { | |
AccountManager accountManager = AccountManager.get(this); | |
accountManager.invalidateAuthToken("com.google", | |
authPreferences.getToken()); | |
authPreferences.setToken(null); | |
} | |
@Override | |
protected void onActivityResult(int requestCode, int resultCode, Intent data) { | |
super.onActivityResult(requestCode, resultCode, data); | |
if (resultCode == RESULT_OK) { | |
if (requestCode == AUTHORIZATION_CODE) { | |
requestToken(); | |
} else if (requestCode == ACCOUNT_CODE) { | |
String accountName = data | |
.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); | |
authPreferences.setUser(accountName); | |
// invalidate old tokens which might be cached. we want a fresh | |
// one, which is guaranteed to work | |
invalidateToken(); | |
requestToken(); | |
} | |
} | |
} | |
private class OnTokenAcquired implements AccountManagerCallback<Bundle> { | |
@Override | |
public void run(AccountManagerFuture<Bundle> result) { | |
try { | |
Bundle bundle = result.getResult(); | |
Intent launch = (Intent) bundle.get(AccountManager.KEY_INTENT); | |
if (launch != null) { | |
startActivityForResult(launch, AUTHORIZATION_CODE); | |
} else { | |
String token = bundle | |
.getString(AccountManager.KEY_AUTHTOKEN); | |
authPreferences.setToken(token); | |
doCoolAuthenticatedStuff(); | |
} | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import android.content.SharedPreferences; | |
import android.content.SharedPreferences.Editor; | |
public class AuthPreferences { | |
private static final String KEY_USER = "user"; | |
private static final String KEY_TOKEN = "token"; | |
private SharedPreferences preferences; | |
public AuthPreferences(Context context) { | |
preferences = context | |
.getSharedPreferences("auth", Context.MODE_PRIVATE); | |
} | |
public void setUser(String user) { | |
Editor editor = preferences.edit(); | |
editor.putString(KEY_USER, user); | |
editor.commit(); | |
} | |
public void setToken(String password) { | |
Editor editor = preferences.edit(); | |
editor.putString(KEY_TOKEN, password); | |
editor.commit(); | |
} | |
public String getUser() { | |
return preferences.getString(KEY_USER, null); | |
} | |
public String getToken() { | |
return preferences.getString(KEY_TOKEN, null); | |
} | |
} |
So I put the
if (authPreferences.getUser() != null && authPreferences.getToken() != null)
Inside a onClick and when I press Ok after selecting a gmail account, the app crashes. I am hoping to use this to do oAuth2 so any help would be greatly appreciated. The question can be found on StackOverflow here http://stackoverflow.com/questions/38968532/app-crashing-after-selecting-gmail-account-oauth2
Joy... I revoked permission of my email to this code and now the permission dialog doesn't show anymore...I now get a BinderProxy error
This gist helped me, thanks! I didn't know "oauth2:" is necessary at the beginning of scope.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks a lot! Helped me from a great trouble.