OAuth 1 authorization with JOAuth, example needed
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!
精彩评论