Since I've seen questions about how to do OAuth 1 3-legged or 2-legged authorization in LinkedIn/Twitter, I thought I'll post an example of how I've achieved to authorize to Twitter with JOAuth.

有帮助吗?

解决方案

This is how to retrieve an Access Token net.oauth.token.v1.AccessToken from Twitter.

First, you will need 2 things from Twitter, which you are required to register your application to Twitter and get an application:

  • API Key (which OAuth calls consumer key)
  • API Secret (which OAuth calls it consumer secret).

Now, Here is the how we'll authenticate to Twitter:

first, let's have our 2 methods that contains our API key & secret:

private static final String API_KEY = "TWITTER_API_KEY_HERE";
private static final String API_SECRET  = "TWITTER_API_SECRET_HERE";

Oh yes, we need a callback_url:

private static final String CALLBACK_URL = "oob";

I'll explain oob (Out-of-Band) later.

Then, we need to create a consumer that will do the OAuth authorization for us:

private OAuth1Consumer consumer = new OAuth1Consumer(API_KEY, API_SECRET, new OAuth1ServiceProvider("https://api.twitter.com/oauth/request_token", "https://api.twitter.com/oauth/authorize", "https://api.twitter.com/oauth/access_token"));

The parameters are as follows: API Key, next is API Secret, OAuth service provider (consisting of Request Token URL, Authorize Token URL, Access Token URL).

Now, let the fun begin:

Requesting a (unauthorized) request Token:

To obtain a request token, we need to call the requestUnauthorizedToken from OAuth1Consumer class:

RequestToken requestToken = consumer.requestUnauthorizedToken(null, CALLBACK_URL, null, new OAuthHmacSha1Signature());

The first parameter is realm which is null (as Twitter doesn't really use it), then the callback_url, and a signature method.

There are 3 valid OAuth Signature method:

  • PLAINTEXT (send as is, in plaintext), class OAuthPlainTextSignature.
  • HMAC-SHA1, class OAuthHmacSha1Signature.
  • RSA-SHA1, class OAuthRsaSha1Signature.

Twitter uses HMAC-SHA1, please refer to documentations when doing OAuth to other providers.

Now that we have an unauthorized request token, let's authorize it.

Authorizing a (unauthorized) request Token:

Authorization requires the user to go to the service provider url and signing in, therefore we need a URL that we can redirect to in our browser.

String url = consumer.createOAuthUserAuthorizationUrl(requestToken, null);

(The 2nd parameter is null as we don't have additional HTTP parameters to send through, but if you do, create a Map<String, String> attributes, fill them and chunk it in the method call :))

Now that we have the URL, chuck the URL to the browser, authorize the application and here is where the callback_url comes in:

Out-Of-Band (OOB) Authorization

OOB authorization is used for applications that can't do an HTTP Redirect but still want to request an Access Token. Twitter states that a PIN is used instead of HTTP Redirect. That PIN (displayed after authorising the Twitter Application) is displayed by Twitter as an image on a browser. For more information, refer to Twitter OAuth API Documentation.

In OOB based call, once you authorized the application, Twitter sends you a PIN: Once you see the pin, to get the Access Token, do the following:

String twitterPin = ""; //Whatever Twitter displayed
AccessToken accessToken = example.requestAccessToken(new AuthorizedToken(requestToken.getToken(), twitterPin), requestToken);

And here we go.

Once you called your access token, the real access token value is on AccessToken.getToken() method.

Callback Redirection (Non OOB)

If you didn't set your callback_url as oob, Twitter will redirect back to your application after authorizing your application with an authorized Token. I have created a process that handled this so we'll need our OAuthServlet to do this for us.

First, we'll need to create a oauth-config.xml under our project's WEB-INF project, like so:

<?xml version="1.0" encoding="UTF-8"?>
<oauth-config>
<!-- Twitter OAuth Config -->
        <oauth name="twitter" version="1">
                <consumer key="TWITTER_KEY" secret="TWITTER_SECRET" />
                <provider requestTokenUrl="https://api.twitter.com/oauth/request_token" authorizationUrl="https://api.twitter.com/oauth/authorize" accessTokenUrl="https://api.twitter.com/oauth/access_token" />
        </oauth>


        <service path="/request_token_ready" class="com.neurologic.example.TwitterOAuthService" oauth="twitter">
                <success path="/start.htm" />
        </service>
</oauth-config>

Then we'll need to configure our web.xml to include OAuthServlet.

<servlet>
    <description>An OAuth Servlet Controller</description>
    <display-name>OAuthServlet</display-name>
    <servlet-name>OAuthServlet</servlet-name>
    <servlet-class>com.neurologic.oauth.servlet.OAuthServlet</servlet-class>
    <init-param>
        <param-name>config</param-name>
        <param-value>/WEB-INF/oauth-config.xml</param-value>
    </init-param>
    <load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>OAuthServlet</servlet-name>
    <url-pattern>/oauth/*</url-pattern>
</servlet-mapping>

And now define a Service. That service will require us to provide it a RequestToken and a realm (if you so wish). My full source code is as follows. I had saved my request token I retrieved above in a session prior to invoking the service.

/**
 * 
 */
package com.neurologic.example;

import javax.servlet.http.HttpServletRequest;

import net.oauth.signature.OAuthSignature;
import net.oauth.signature.impl.OAuthHmacSha1Signature;
import net.oauth.token.v1.AccessToken;
import net.oauth.token.v1.RequestToken;

import com.neurologic.oauth.service.impl.OAuth1Service;

/**
 * @author Buhake Sindi
 * @since 31 May 2011
 *
 */
public class TwitterOAuthService extends OAuth1Service {

    public static final String TWITTER_REQUEST_TOKEN_SESSION = "TWITTER_REQUEST_TOKEN_SESSION";
    public static final String TWITTER_ACCESS_TOKEN_SESSION = "TWITTER_ACCESS_TOKEN_SESSION";

    /* (non-Javadoc)
     * @see com.neurologic.oauth.service.impl.OAuth1Service#getOAuthSignature()
     */
    @Override
    protected OAuthSignature getOAuthSignature() {
        // TODO Auto-generated method stub
        return new OAuthHmacSha1Signature();
    }

    /* (non-Javadoc)
     * @see com.neurologic.oauth.service.impl.OAuth1Service#getRealm()
     */
    @Override
    protected String getRealm() {
        // TODO Auto-generated method stub
        return null;
    }

    /* (non-Javadoc)
     * @see com.neurologic.oauth.service.impl.OAuth1Service#getRequestToken(javax.servlet.http.HttpServletRequest)
     */
    @Override
    protected RequestToken getRequestToken(HttpServletRequest request) {
        // TODO Auto-generated method stub
        return (RequestToken) request.getSession().getAttribute(TWITTER_REQUEST_TOKEN_SESSION);
    }

    /* (non-Javadoc)
     * @see com.neurologic.oauth.service.OAuthService#saveAccessToken(javax.servlet.http.HttpServletRequest, java.lang.Object)
     */
    @Override
    public void saveAccessToken(HttpServletRequest request, AccessToken accessToken) {
        // TODO Auto-generated method stub
        request.getSession().setAttribute(TWITTER_ACCESS_TOKEN_SESSION, accessToken);
    }
}

The saveAccessToken() method from the service is the method called by the service when the Access Token is received by Twitter (I'm using Twitter as an example, but feel free to use any service provider).

The Servlet handles the handshaking from authorizing my request token and retrieving an access token without me writing extra flow code.

I hope this helps everyone!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top