Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OAuth instance state in Android

Tags:

android

oauth

I'm trying to use OAuth in an Android app. I have it working correctly but have sometimes run into a problem during the authentication phase. In Android, I launch the browser for the user to login and authenticate. Then the callback url will redirect back to my application.

Here is the problem. My application has a OAuth consumer and provider as members of my main class. When the browser is launched for authentication, sometimes my main Activity is discarded to save memory. When the callback url relaunches my main Activity, the provider and consumer are new instances and therefor don't work when I try to make a request to the api. If the main Activiy was not freed during the authentication phase, then everything works correctly because I'm still working with the original consumer and provider.

I tried using onSaveInstanceState() and onRestoreInstanceState(), but haven't been successful. It seems the onRestoreInstanceState() is not called when my callback url is handled. Seems to go straight to the onResume().

What is the correct method for persisting the consumer and provider in this case?

like image 716
GrkEngineer Avatar asked Dec 27 '09 09:12

GrkEngineer


2 Answers

Complete Save / restore solution

Apart from the request_token and token_secret, the isOauth10a() state is important to be restored in the provider. There could be more state information in the future. Hence, I like the persist and load solution the best.

I extended GrkEngineer's solution to be more complete. It saves / restores both the provider and consumer, handles all exceptions, and sets the httpClient while restoring.

protected void loadProviderConsumer()
{
  try {
    FileInputStream fin = this.openFileInput("tmp_provider.dat");
    ObjectInputStream ois = new ObjectInputStream(fin);
    provider = (CommonsHttpOAuthProvider) ois.readObject();
    provider.setHttpClient(httpClient);
    ois.close();
    fin.close();

    fin = this.openFileInput("tmp_consumer.dat");
    ois = new ObjectInputStream(fin);
    consumer = (CommonsHttpOAuthConsumer) ois.readObject();
    ois.close();
    fin.close();

    Log.d("OAuthTwitter", "Loaded state");
  } catch (FileNotFoundException e) {
    e.printStackTrace();
  } catch (StreamCorruptedException e) {
    e.printStackTrace();
  } catch (IOException e) {
    e.printStackTrace();
  } catch (ClassNotFoundException e) {
    e.printStackTrace();
  }
}

protected void persistProviderConsumer()
{

  try {
    FileOutputStream fout = this.openFileOutput("tmp_provider.dat", MODE_PRIVATE);
    ObjectOutputStream oos = new ObjectOutputStream(fout);
    oos.writeObject(provider);
    oos.close();
    fout.close();

    fout = this.openFileOutput("tmp_consumer.dat", MODE_PRIVATE);
    oos = new ObjectOutputStream(fout);
    oos.writeObject(consumer);
    oos.close();
    fout.close();

    Log.d("OAuthTwitter", "Saved state");
  } catch (FileNotFoundException e) {
    e.printStackTrace();
  } catch (IOException e) {
    e.printStackTrace();
  }
}

I have tested this code and it works.

like image 117
HRJ Avatar answered Oct 15 '22 17:10

HRJ


You can read my old post here. Generally what I've done was to use static reference and using Activity with WebView instead of standalone browser to display authentication form

like image 42
Bostone Avatar answered Oct 15 '22 18:10

Bostone