Created
June 6, 2011 01:44
-
-
Save DomDerrien/1009626 to your computer and use it in GitHub Desktop.
OAuth authentication handling in a Android application
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
<?xml version="1.0" encoding="utf-8"?> | |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |
package="twetailer.console" | |
android:versionName="0.1" android:versionCode="1"> | |
<uses-sdk android:minSdkVersion="8" /> | |
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission> | |
<uses-permission android:name="android.permission.INTERNET"></uses-permission> | |
<application android:label="@string/app_name" android:icon="@drawable/ase_men"> | |
<activity android:name=".Dashboard" | |
android:label="@string/app_name" android:launchMode="singleTop"> | |
<intent-filter> | |
<action android:name="android.intent.action.MAIN" /> | |
<category android:name="android.intent.category.LAUNCHER" /> | |
</intent-filter> | |
<intent-filter> | |
<action android:name="android.intent.action.VIEW"/> | |
<category android:name="android.intent.category.DEFAULT" /> | |
<category android:name="android.intent.category.BROWSABLE"/> | |
<data android:scheme="ase" android:host="oauthresponse"/> | |
</intent-filter> | |
</activity> | |
<activity android:name="Preferences" android:label="@string/pref_name"> | |
</activity> | |
</application> | |
</manifest> |
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
package twetailer.console; | |
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer; | |
import oauth.signpost.commonshttp.CommonsHttpOAuthProvider; | |
import twetailer.oauth.OAuthDefs; | |
import android.app.Activity; | |
import android.content.Intent; | |
import android.net.Uri; | |
import android.os.Bundle; | |
import android.preference.PreferenceManager; | |
import android.util.Log; | |
import android.view.View; | |
import android.view.View.OnClickListener; | |
import android.widget.CheckBox; | |
import android.widget.Toast; | |
public class Dashboard extends Activity { | |
private static CommonsHttpOAuthConsumer consumer = null; | |
private static CommonsHttpOAuthProvider provider = null; | |
/** Called when the activity is first created. */ | |
@Override | |
public void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
Preferences.setPreferenceContext(PreferenceManager.getDefaultSharedPreferences(getBaseContext())); | |
boolean justAuthenticated = checkOAuthReturn(getIntent()); | |
if (!justAuthenticated && Preferences.get(Preferences.OAUTH_KEY, "").length() == 0) { | |
// Display the pane with the warning message and the sign in button | |
setContentView(R.layout.main_noauth); | |
// Update the 'Remember me' checkbox with its last saved state, or the default one | |
final String saveOAuthKeysPrefs = Preferences.get(Preferences.SAVE_OAUTH_KEYS, Preferences.SAVE_OAUTH_KEYS_DEFAULT); | |
((CheckBox) findViewById(R.id.app_noauth_keepmeconnected)).setChecked(Preferences.SAVE_OAUTH_KEYS_YES.equals(saveOAuthKeysPrefs)); | |
// Attach the event handler that will initiate the authorization process up to opening the browser with the authorization page | |
findViewById(R.id.app_noauth_continue).setOnClickListener(new OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
// Check if the 'Keep me connected' check box state changed and save its new state | |
boolean keepMeConnected = ((CheckBox) findViewById(R.id.app_noauth_keepmeconnected)).isChecked(); | |
if (Preferences.SAVE_OAUTH_KEYS_YES.equals(saveOAuthKeysPrefs) != keepMeConnected) { | |
Preferences.set(Preferences.SAVE_OAUTH_KEYS, keepMeConnected ? Preferences.SAVE_OAUTH_KEYS_YES : Preferences.SAVE_OAUTH_KEYS_NO); | |
} | |
// Set up the OAuth library | |
consumer = new CommonsHttpOAuthConsumer("<your_app_public_key>", "<your_app_secret_key>"); | |
provider = new CommonsHttpOAuthProvider( | |
"https://<your_app_id>.appspot.com/_ah/OAuthGetRequestToken", | |
"https://<your_app_id>.appspot.com/_ah/OAuthAuthorizeToken", | |
"https://<your_app_id>.appspot.com/_ah/OAuthGetAccessToken"); | |
try { | |
// Steps 1 & 2: | |
// Get a request token from the application and prepare the URL for the authorization service | |
// Note: the response is going to be handled by the application <intent/> registered for that custom return URL | |
String requestTokenUrl = provider.retrieveRequestToken(consumer, "ase://oauthresponse"); | |
// Step 3: | |
// Invoke a browser intent where the user will be able to log in | |
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(requestTokenUrl))); | |
} | |
catch(Exception ex) { | |
Toast.makeText(Dashboard.this, R.string.app_noauth_requesttoken_ex, Toast.LENGTH_LONG).show(); | |
Log.e("Dashboard no auth", "Cannot initiate communication to get the request token\nException: " + ex.getClass().getName() + "\nMessage: " + ex.getMessage()); | |
} | |
} | |
}); | |
} | |
else { | |
setContentView(R.layout.main); | |
} | |
} | |
@Override | |
protected void onNewIntent(Intent intent) { | |
checkOAuthReturn(intent); | |
} | |
private boolean checkOAuthReturn(Intent intent) { | |
boolean returnFromAuth = false; | |
Uri uri = intent.getData(); | |
if (uri != null && uri.toString().startsWith("ase://oauthresponse")) { | |
// Step 4: | |
// Get the request token from the Authentication log in page | |
String code = uri.getQueryParameter("oauth_verifier"); | |
try { | |
// Step 5: | |
// Get directly the access tokens | |
provider.retrieveAccessToken(consumer, code); | |
Log.e("Dashboard no auth", "User authenticated"); | |
returnFromAuth = true; | |
// Persist the tokens | |
if (Preferences.SAVE_OAUTH_KEYS_YES.equals(Preferences.get(Preferences.SAVE_OAUTH_KEYS, Preferences.SAVE_OAUTH_KEYS_DEFAULT))) { | |
Preferences.set(Preferences.OAUTH_KEY, consumer.getToken()); | |
Preferences.set(Preferences.OAUTH_SECRET, consumer.getTokenSecret()); | |
Log.e("Dashboard no auth", "User tokens persisted as preferences"); | |
} | |
} | |
catch(Exception ex) { | |
Toast.makeText(Dashboard.this, R.string.app_noauth_accesstoken_ex, Toast.LENGTH_LONG).show(); | |
Log.e("Dashboard no auth", "Cannot complete communication to get the request token\nException: " + ex.getClass().getName() + "\nMessage: " + ex.getMessage()); | |
} | |
} | |
return returnFromAuth; | |
} | |
} |
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
<?xml version="1.0" encoding="utf-8"?> | |
<LinearLayout | |
xmlns:android="http://schemas.android.com/apk/res/android" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:orientation="vertical" | |
> | |
<LinearLayout | |
android:layout_height="wrap_content" | |
android:layout_width="match_parent" | |
android:orientation="horizontal" | |
> | |
<ImageView | |
android:layout_height="wrap_content" | |
android:layout_width="wrap_content" | |
android:src="@drawable/ase_network" | |
android:layout_margin="5dip" | |
android:layout_gravity="top" | |
></ImageView> | |
<TextView | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="@string/app_noauth_warning" | |
android:layout_marginRight="5dip" | |
android:layout_marginTop="5dip" | |
android:layout_marginBottom="5dip" | |
></TextView> | |
</LinearLayout> | |
<CheckBox | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:checked="true" | |
android:text="@string/app_noauth_keepmeconnected" | |
android:layout_gravity="center_horizontal" | |
android:id="@+id/app_noauth_keepmeconnected" | |
></CheckBox> | |
<Button | |
android:text="@string/btn_continue" | |
android:layout_height="wrap_content" | |
android:layout_width="wrap_content" | |
android:id="@+id/app_noauth_continue" | |
android:layout_gravity="center_horizontal" | |
></Button> | |
</LinearLayout> |
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
package twetailer.console; | |
import android.content.SharedPreferences; | |
import android.preference.PreferenceActivity; | |
import android.util.Log; | |
public class Preferences extends PreferenceActivity { | |
protected static SharedPreferences appPrefs; | |
protected static final String OAUTH_KEY = "oauthKey"; | |
protected static final String OAUTH_SECRET = "oauthSecret"; | |
protected static final String SAVE_OAUTH_KEYS = "saveOAuthKeys"; | |
protected static final String SAVE_OAUTH_KEYS_YES = "Y"; | |
protected static final String SAVE_OAUTH_KEYS_NO = "N"; | |
protected static final String SAVE_OAUTH_KEYS_DEFAULT = SAVE_OAUTH_KEYS_NO; | |
protected static void setPreferenceContext(SharedPreferences preferences) { | |
appPrefs = preferences; | |
} | |
protected static String get(String key, String defaultValue) { | |
try { | |
return appPrefs.getString(key, defaultValue); | |
} | |
catch(Exception ex) { | |
return set(key, defaultValue); | |
} | |
} | |
public static String set(String key, String value) { | |
SharedPreferences.Editor editor = appPrefs.edit(); | |
editor.putString(key, value); | |
editor.commit(); | |
return value; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment