tags:

views:

483

answers:

4

Hi, i am trying to authenticate something(in this case LinkedIn) using OAuth but the requested token always returns null?

Here is my code below:

public void authenticateAppOauthApi() {
        Log.d(TAG, "authenticateAppOauthApi");

        OAuthServiceProvider provider = new OAuthServiceProvider(
                REQUEST_TOKEN_PATH, AUTHORIZE_PATH, ACCESS_TOKEN_PATH);

        OAuthConsumer consumer = new OAuthConsumer(CALLBACK_URL, API_KEY,
                SECRET_KEY, provider);

        OAuthAccessor accessor = new OAuthAccessor(consumer);

        Intent intent = new Intent(Intent.ACTION_VIEW);
        Log.d(TAG, "Intent intent = new Intent(Intent.ACTION_VIEW );");
        // intent.setData(Uri.parse(url));
        String url = accessor.consumer.serviceProvider.userAuthorizationURL
                + "?oauth_token=" + accessor.requestToken + "&oauth_callback="
                + accessor.consumer.callbackURL;

        intent.setData(Uri.parse(url));
        Log.d(TAG, "intent.setData(Uri.parse(url)); = " + url);
        mContext.startActivity(intent);

        Log.d(TAG, "finish authenticateApp");
}

I basicaly followed the example here http://donpark.org/blog/2009/01/24/android-client-side-oauth

thanks in advance

A: 

Just a idea, Is it HTTP URL or HTTPS URL ?

I had some problem to access HTTPS URL, browser & app told that certificate was wrong.

Some Root Certificate are not known by Android.

NSchubhan
Yes its a HTTPS url but it doesnt tell me anything about certificates. it just launches the browser with an error loading the authentication page because of the request token being null.The example i have found all use the old Signpost 1.1 but when you go to the Signpost http://code.google.com/p/oauth-signpost/downloads/list its 1.2 and many of the objects used in previous examples do not work.
jonney
A: 

I had some trouble using one of the OAuth libs I found on the net in my Scala Android app. Instead of finding a way to use the lib I just rolled my own... Not sure if it would work against linkedin (it works well with Yammer, which uses HTTPS). Well, below is the relevant code, mind you I'm pretty new to both Android and Scala so there are probably better ways to accomplish this.

The layout file "R.layout.authorization" is very basic contains with two buttons and a text field in a RelativeLayout.

class Authorization extends Activity {

  val client = new DefaultHttpClient()
  val reqUrl = "https://www.yammer.com/oauth/request_token"
  val authUrl = "https://www.yammer.com/oauth/authorize?oauth_token="
  val accessUrl = "https://www.yammer.com/oauth/access_token"

  override def onCreate(bundle:Bundle) = {
    super.onCreate(bundle)
    this.setContentView(R.layout.authorization)

    val authButton = findViewById(R.id.authButton).asInstanceOf[Button]
    val getCodeButton = findViewById(R.id.getCode).asInstanceOf[Button]

    val prefs = getSharedPreferences(PreferenceFile(), 0)
    if(prefs.contains("oauth_request_token")) { 
      authButton.setVisibility(View.VISIBLE)
    }

    setupListeners(authButton, getCodeButton) 
  }

  private def getAuthVerifier() = { 
    val authVerifierBox:EditText = Authorization.this.findViewById(R.id.authVerifier).asInstanceOf[EditText]
    if(authVerifierBox != null && authVerifierBox.getText() != null) {
      authVerifierBox.getText().toString()    
    } else {
      ""
    }
  }

  private def setupListeners(authButton:Button, getCodeButton:Button) = {
    authButton.setOnClickListener(new View.OnClickListener() {
      override def onClick(view:View) = {
        retrieveAuthTokenAndSecret()  
      }
    })
    getCodeButton.setOnClickListener(new View.OnClickListener() {
      override def onClick(view:View) = {
        try {
          // Retrieve a request token with an async task and then start the browser...
          // Use of an implicit definition to convert tuple to an async task.
          (() => {
              // Task to perform
              val reqPost = new HttpPost(reqUrl)
              reqPost.setHeader("Authorization", OAuthHeaderBuilder(null,null,null))
              reqPost.setHeader("Content-Type", "application/x-www-form-urlencoded")
              val reqResp= client.execute(reqPost)
              reqResp.getEntity()
          },  
           (entity:HttpEntity) => {
            // PostExecute handle result from task...
            if(entity != null) {
              val reader = new BufferedReader(new InputStreamReader(entity.getContent()))
              val line = reader.readLine()
              val (oauth_request_token, oauth_token_secret) = OAuthTokenExtractor(line)

              // Store request tokens so they can be used when retrieving auth tokens...
              val editor = getSharedPreferences(PreferenceFile(), 0).edit()
              editor.putString("oauth_request_token", oauth_request_token)
              editor.putString("oauth_token_secret", oauth_token_secret)
              editor.commit()

              // Start browser...
              val intent = new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl + oauth_request_token))
              startActivity(intent)
              val authButton = findViewById(R.id.authButton).asInstanceOf[Button]
              authButton.setVisibility(View.VISIBLE)                
            }
          }).doInBackground()
        } catch {
          case e:Exception => Log.e("ERROR", "ERROR IN CODE:"+e.toString())
        }
      }
    })
  }

  private def retrieveAuthTokenAndSecret() = {
    val authVerifier = getAuthVerifier()  
    val accessPost = new HttpPost(accessUrl)
    val prefs = getSharedPreferences(PreferenceFile(), 0)
    val token = prefs.getString("oauth_request_token","")
    val secret = prefs.getString("oauth_token_secret","")
    accessPost.setHeader("Authorization", OAuthHeaderBuilder(token, secret, authVerifier))
    accessPost.setHeader("Content-Type", "application/x-www-form-urlencoded")
    val accessResp = client.execute(accessPost)
    val entity = accessResp.getEntity()
    if(entity != null) {
      val reader = new BufferedReader(new InputStreamReader(entity.getContent()))
      val builder = new StringBuilder()
      val line = reader.readLine()
      val (oauth_token, oauth_token_secret) = OAuthTokenExtractor(line)
      val result = new Intent()
      val editor = getSharedPreferences(PreferenceFile(), 0).edit()
      editor.putString("oauth_token", oauth_token)
      editor.putString("oauth_token_secret", oauth_token_secret)
      editor.commit()

      setResult(Activity.RESULT_OK, result)
      finish()
    }
  } 
}

The OAuthHeaderBuilder is basically a copy of the Yammer oauth sample code:

object OAuthHeaderBuilder {
  // Apply function taken from the Yammer oauth sample 
  def apply(token:String, secret:String,verifier:String):String = {
    val buff = new StringBuilder()
    val currentTime = System.currentTimeMillis()
    // Hardcoded values for consumer key and secret...
    val consumerKey = "<your consumer key here>"
    val consumerSecret = "<your consumer secret here>"
    buff.append("OAuth realm=\"");
    buff.append("\", oauth_consumer_key=\"");
    buff.append(consumerKey);
    buff.append("\", ");

    if (token != null) {
      buff.append("oauth_token=\"");
      buff.append(token);
      buff.append("\", ");
    }

    buff.append("oauth_signature_method=\"");
    buff.append("PLAINTEXT");
    buff.append("\", oauth_signature=\"");
    buff.append(consumerSecret);
    buff.append("%26");
    if (secret != null) {
      buff.append(secret);
    }
    buff.append("\", oauth_timestamp=\"");
    buff.append(currentTime);
    buff.append("\", oauth_nonce=\"");
    buff.append(currentTime);

    if (verifier != null) {
      buff.append("\", ");
      buff.append("oauth_verifier=\"");
      buff.append(verifier);
    }

    buff.append("\", oauth_version=\"1.0\"");

    return buff.toString();
  }
}

And inorder to extract the tokens I made a OAuthTokenExtractor object...

object OAuthTokenExtractor {
  def apply(line:String) = {
    val token = (line split ("&")).find(x => x.startsWith("oauth_token=")) match {
      case Some(oauth_token) => (oauth_token split ("=") )(1)
      case _ => ""
    }   
    val secret = (line split ("&")).find(x => x.startsWith("oauth_token_secret=")) match {
      case Some(oauth_token_secret) => (oauth_token_secret split ("=") )(1)
      case _ => ""
    }   
    (token,secret)
  }
}

Hope it helps :)

Emil H
A: 

Better use this article as a reference:

There is a code to get authentication URL in current version of Signpost is:

provider.retrieveRequestToken(CALLBACK_URL);

(and be sure to use CommonsHttpOAuthConsumer and CommonsHttpOAuthProvider)

shaman.sir
A: 

you can try this code.

OAuthClient oAuthClient = new OAuthClient(new HttpClient4()); try { oAuthClient.getRequestToken(accessor); } catch (IOException e) { e.printStackTrace(); } catch (OAuthException e) { e.printStackTrace(); } catch (URISyntaxException e) { e.printStackTrace();

Herbert