Add OAuth authentication support to HttpClient

With modern web applications, accessing resources using the HTTP protocol can be cumbersome. In this article, learn how HttpClient's authentication modules can help provide OAuth authentication support. Learn to extend the authentication module to use a customized authentication scheme. An example, including sample code, shows you how to use the open source library provided by oauth.net to add OAuth authentication support to the HttpClient component.

Share:

Zheng (Erik) Bi, Staff Software Engineer, IBM

Zheng Bi photoZheng Bi works on the J2EE/Web2.0 aspect of IBM products, including WBSE and IBM Mashup Center. He has a lot of experience with web application development technologies. Zheng is currently working on Web 2.0 securities.



Xiaofeng Yu, Advisory Software Engineer, IBM

Xiaofeng Yu photoXiaofeng Yu joined IBM in 2005. He has extensive experience in web application development, and has worked on IBM Web 2.0 products, Lotus Connections, and Lotus Mashups. Xiaofeng is currently working on Web 2.0 securities.



14 December 2010

Also available in Chinese Japanese

Introduction

HTTP is the Internet protocol we all know. Though the java.net package provides basic functions to access resources via HTTP protocol, it is neither flexible nor powerful enough to meet the requirements of modern web applications. The Apache Jakarta Commons HttpClient addresses the gap by providing an efficient and feature-rich package implementation on the client side using the most recent HTTP standards and recommendations. HttpClient has been widely adopted in open source projects and commercial software products.

In this article, learn how to extend the authentication module of HttpClient. Use the third-party OAuth library to add OAuth authentication. This article also discusses the differences between HttpClient v3.0.x and v4.x.


Authentication mechanism

HttpClient handles authenticating with servers almost transparently. All you have to do is provide the login credentials. There is a difference between releases, however.

HttpClient v3.x
Credentials are stored in the HttpState instance and can be set or retrieved using the setCredentials(AuthScope authscope, Credentials cred) and getCredentials(AuthScope authscope) methods. The automatic authorization built into HttpClient can be disabled with the method setDoAuthentication(boolean doAuthentication) in the HttpMethod class. The change only affects that method instance.

Preemptive basic authentication is supported by setting setAuthenticationPreemptive(Boolean preemptive), but only preemptive basic authentication is supported.

HttpClient v4.x
You should instantiate CredentialProvider to maintain the set of user credentials and provide a credential for a particular authentication scope. By adding CredentialProvider into HttpContext, which represents the execution state of an HTTP process, HttpClient is able to do authentication automatically according to the host name, port, and realm.

Preemptive authentication is no longer provided out of the box. Misuse of preemptive authentication may cause the leak of user credentials. However, if you want preemptive authentication you can enable it by using a standard HttpClient extension, such as protocol interceptor.


OAuth

OAuth is an open protocol that allows secure API authorization in a simple and standard method from desktop and web applications. With OAuth, a resource owner can authorize third party application access to the protected resource without compromising user credentials. (The OAuth protocol was stabilized at version 1.0 in 10/07 and revised in 6/09 (Revision A). The OAuth 2.0 specification is under development.)

Figure 1 shows the typical three-legged OAuth dance.

Figure 1. Three-legged OAuth dance
Diagram showing the Browser, Consumer, and Service Provider with the ten steps outlined in the text below.

Per the numbers in the figure above, when the OAuth three-legged handshake starts:

  1. The consumer requests a temporary token for the OAuth handshake. This token is used to maintain the handshake session.
  2. After validating the consumer, the service provider issues a short-term request token.
  3. The consumer sends an HTTP redirect response to the user's browser and leads the user to the service provider for authorization.
  4. The user reviews the authorization request and grants access to the consumer on the service provider site if he trusts the consumer.
  5. The service provider confirms the authorization and sends an HTTP redirect response to the user's browser.
  6. The user's browser is redirected to the consumer's callback URL, where the consumer can complete the remaining part of the handshake.
  7. The consumer requests the access token from the service provider with a verifier passed in the previous step.
  8. Upon successful validation, the service provider issues the access token to access the protected resources.
  9. After the OAuth handshake completes, the access token is issued and the consumer can use the access token to access the protected resources on behalf of the user.
  10. The service provider validates each incoming OAuth request and returns the protected resources if the consumer is authorized.

When OAuth-protected resources are requested, typically the client will get an HTTP 401 response including a WWW-Authentication header:

WWW-Authenticate: OAuth realm=<your_realm>

The WWW-Authentication header points out the authentication schemes of the protected resources. The HttpClient is then able to perform OAuth authentication according to the WWW-Authenticate header.

By default, only basic, digest, and NTLM authentication schemes are supported in HttpClient. The next section introduces how to add and use OAuth authentication schemes in HttpClient.

Add a customized authentication scheme

In addition to natively supporting basic, digest, and NTLM authentication, HttpClient has a mechanism to plug in additional custom authentication schemes using the AuthScheme interface. To use a custom authentication scheme:

  1. Implement the AuthScheme interface.
  2. Register the custom AuthScheme with AuthPolicy.registerAuthScheme().
  3. Include the custom AuthScheme in the AuthPolicy.AUTH_SCHEME_PRIORITY preference (see HttpClient 3.0.x OAuth support later in this article).

Use oauth.net's Java library to extend HttpClient 4.0.1

Oauth.net provides an open source Java™ Library. As mentioned, to use customized authentication you need to provide your own AuthScheme and credential class. The OAuth library has already implemented its own OAuthScheme, OAuthSchemeFactory, and OAuthCredentials. You can leverage them to add OAuth authentication support to your HttpClient application.

To enable an OAuth authentication scheme for HttpClient 4.0.1:

  1. Register the new OAuth authentication scheme in HttpClient.
  2. Provide a new OAuthCredentials.
  3. HttpClient uses an order of preference to select the correct authentication scheme. You can use the local HttpContext object to customize the HTTP authentication context prior to requesting execution, or you can examine its state after the request has been executed. Alter the preference of the authentication schemes by setting the attribute http.auth.scheme-pref of the HttpContext object.

Listing 1 shows an example. Note that the means to get your own OAuthAccessor is omitted in the code since it depends on your specific implementation.

Listing 1. Enable an OAuth authentication scheme for HttpClient 4.0.1
AbstractHttpClient httpClient = new DefaultHttpClient();
//register the OAuthScheme
httpClient.getAuthSchemes().register(OAuthSchemeFactory.SCHEME_NAME, 
new OAuthSchemeFactory()); 
//get the OAuthAccessor object
OAuthAccessor accessor = yourMethodToGetOAuthAccessor();
//set credentials 
httpClient.getCredentialsProvider().setCredentials(
new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM,
OAuthSchemeFactory.SCHEME_NAME),
new OAuthCredentials(accessor));
//Adjust the authentication scheme selection
HttpContext localContext = new BasicHttpContext();
localContext.setAttribute("http.auth.scheme-pref", Arrays.asList(new String[] {
"oauth", "digest", "basic"
}));

Example: Get profile from LinkedIn using OAuth

Many web sites, such as LinkedIn, support OAuth. The following example shows how to get a user profile from LinkedIn using HttpClient with OAuth support.

  1. You need to have a LinkedIn account and create an application. You can then get the API Key, which is also called a Consumer Key in OAuth terminology. Figure 2 shows an example.
    Figure 2. Get Consumer Key and Secret for your application
    Screenshot showing the message that the application was successfully created, with application details including Company, Application name, API Key, and Secret Key.
  2. With the Consumer Key and Secret Key, raise a request to LinkedIn to get the AccessToken and Secret using the following:
    • LinkedIn Oauth endpoint URL
    • Base: https://api.linkedin.com
    • Request token path: /uas/oauth/requestToken
    • Access token path: /uas/oauth/accessToken
    • Authorize path: /uas/oauth/authorize

    Listing 2 shows the sample code.

    Listing 2. Get the AccessToken and Secret from LinkedIn
    String baseURL = "https://api.linkedin.com";
    String requestTokenURL = baseURL + "/requestToken";
    String authorizationURL = baseURL + "/authorize";
    String accessTokenURL = baseURL + "/accessToken";
    
    String consumerKey="hP80ApmoJkO-9ZHuXC97olUzD1egVI75zKoff9SCKFFTY9zjc
       vWRRRbiNrWbcKIX";
    String consumerSecret="toAk3oV1wKuon9W51lfELLHtZSxBZHih-qMyeDIBrIB2Y1hCASbpmK313
       Wubmrd2";
    OAuthServiceProvider provider = new OAuthServiceProvider(
    				requestTokenURL, authorizationURL, accessTokenURL);
    OAuthConsumer consumer = new OAuthConsumer(
    		"DemoOAuth", consumerKey, consumerSecret, provider);
    OAuthAccessor accessor = new OAuthAccessor(consumer);
    OAuthClient client = new OAuthClient(new HttpClient4());
    List<Parameter> parameters = new ArrayList<OAuth.Parameter>();
    parameters.add(new Parameter("oauth_callback", "yourAppcallbackurl"));
    OAuthMessage msg = client.getRequestTokenResponse(accessor,
    					"POST", parameters);
    String requestToken = msg.getParameter(OAuth.OAUTH_TOKEN);
    String requestSecret = msg.getParameter(OAuth.OAUTH_TOKEN_SECRET);

    You should now have the URL:

    authorizationURL + "?" + OAuth.OAUTH_TOKEN+ "=" + requestToken

    The user should visit, or be redirected if in a web application, to LinkedIn for approval, as shown below.

    Figure 3. User approval
    Screen shot showing the process of granting OAuth access to your LinkedIn account

    In your own callback servlet, use the code below in Listing 3 to get the verifier and use it to request AccessToken and Secret.

    Listing 3. Request AccessToken and Secret
    OAuthMessage msg = OAuthServlet.getMessage(request, null);
    String requestToken = msg.getParameter(OAuth.OAUTH_TOKEN);
    String verifier = msg.getParameter(OAuth.OAUTH_VERIFIER);
    …
    get the accessor object in List 1…
    ….
    OAuthClient oauthClient = new OAuthClient(new HttpClient4());
    List<Parameter> list = new ArrayList<Parameter>();
    list.add(new Parameter(OAuth.OAUTH_VERIFIER, verifier));
    OAuthMessage returned = oauthClient.getAccessToken(accessor,
           "POST", list);
    String accessToken = returned.getParameter(OAuth.OAUTH_TOKEN));
    String accessKey = returned.getParameter(OAuth.OAUTH_TOKEN_SECRET));
  3. Add OAuth support to HttpClient.

    With the code in the previous section, register the OAuthScheme. Use the accessor object to set the credentials.

  4. Send the request to LinkedIn with OAuth authentication.
    Listing 4. Send the request to LinkedIn with OAuth authentication
    HttpGet httpget = new HttpGet("https://api.linkedin.com/v1/people/~");
    //Run the http get method under the modified context
    httpClient.execute(httpget, localContext);

    Now you can get the user profile via HttpClient using OAuth authentication, as shown in Listing 5.

    Listing 5. LinkedIn returns user info
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <person>
      <first-name>Zheng</first-name>
      <last-name>BI</last-name>
      <headline>SE at IBM</headline>
      <site-standard-profile-request>
    <url>http://www.linkedin.com/profile?viewProfile=&amp;key=84546207
    &amp;authToken=SMl9&amp;authType=name&amp;
    trk=api*a113393*s121886*</url>
      </site-standard-profile-request>
    </person>

Preemptive mode support

HttpClient does not support preemptive authentication out of the box, but you can use a protocol interceptor to preemptively introduce an AuthScheme instance to the execution context. The interceptor must be added to the protocol processing chain before the standard authentication interceptors.

Web sites that only support OAuth 1.0 don't provide the "challenge" response. To use OAuth authentication you need to use preemptive authentication. The OAuth library also implements it with HttpRequestInterceptor for HttpClient 4.0.1. Listing 6 shows sample code to enable preemptive authentication.

Listing 6. Enable preemptive authentication
HttpRequestInterceptor preemptiveAuth = new PreemptiveAuthorizer();
httpClient.addRequestInterceptor(preemptiveAuth, 0);

HttpClient 3.0.x OAuth support

HttpClient natively supports basic, digest, and NTLM authentication. Adding a customized AuthScheme in HttpClient 3.0.x is different from 4.0.1.

  1. OAuth Java Lib doesn't provide support for HttpClient 3.0.x, so you need to create your own Scheme class that implements the AuthScheme interface. Details about writing functions are outside the scope of this article.
  2. Register the OAuthScheme using AuthPolicy.registerAuthScheme() (see http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/auth/AuthPolicy.html#registerAuthScheme%28java.lang.String,%20java.lang.Class%29).
  3. Alter the AuthPolicy.AUTH_SCHEME_PRIORITY preference to enable the customized AuthScheme, as shown below.
    Listing 7. Enable the customized AuthScheme
    HttpClient client = new HttpClient();
    List authPrefs = new ArrayList(2);
    authPrefs.add(AuthPolicy.OAUTH);
    authPrefs.add(AuthPolicy.DIGEST);
    authPrefs.add(AuthPolicy.BASIC);
    client.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);

Limitation of v3.0.x

HttpClient 3.0.x also supports preemptive authentication, as follows.

Listing 8. HttpClient 3.0.x supports preemptive authentication
client.getParams().setAuthenticationPreemptive(true);

However, in this mode you can only use basic authentication. For a website that requires preemptive authentication for OAuth, you cannot use HttpClient 3.0.x.


Conclusion

The HttpClient authentication module provides a mechanism to extend itself. For applications that use HttpClient during development, leveraging a third party OAuth library to add OAuth authentication is fairly easy. There are some limitations for HttpClient 3.0.x, however.

Resources

Learn

  • Read the OAuth 1.0 Protocol, which is a product of the Internet Engineering Task Force (IETF) and represents the consensus of the IETF community.
  • Learn more about HttpCore and HttpClient 4.1 from Apache.
  • Read about authentication mechanisms to authenticate with HTTP servers or proxies.
  • Visit OAuth.net for information on every aspect of OAuth 1.0 and 2.0, including code related to OAuth protocol implementation such as the Java OAuth library used in this article.
  • Explore the LinkedIn DeveloperNetwork to find LinkedIn open APIs.

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Web development on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development
ArticleID=600970
ArticleTitle=Add OAuth authentication support to HttpClient
publish-date=12142010