ApacheCon 2011 : Web Services Security - Patterns, Practices and Threats

I'll be conducting a training on "Web Services Security - Patterns, Practices and Threats" at ApacheCon this time. Would be on 7th November from 2.30 PM to 5.30 PM. If you are planning to attend ApacheCon, now it's open for registration.

During this session I'll be covering the practical importance of security standards like, WS-Security, WS-Security Policy, WS-Trust and risks associated with those. Further the session will cover patterns, best practices and threats associated with SOA security models.

Integrating 3-legged OAuth with XACML

This blog post explains in detail how to integrate 3-legged OAuth with XACML. Detailed explanations on OAuth and XACML are out of scope.

You need to download following products to get the sample running.

1. WSO2 Identity Server - acting as the service provider, where a user can register an OAuth consumer app to obtain a request token, authorize it and obtain an access token. Also WSO2 Identity Server is used as the XACML engine. Identity Server can be downloaded from here.

2. WSO2 ESB - acting as an interceptor to the final resource the consumer wants to access. ESB will intercept the request and performs OAuth validation. WSO2 ESB can be downloaded from here.

3. WSO2 Application Server - this is used to host WSO2 OAuth Playground web app. App Server can be downloaded from here.

4. Download and unzip the sample from here to OAUTH_SAMPLE.

Let's first start by setting up the WSO2 Identity Server.


1. Unzip the downloaded copy of Identity Server and remove all jars starting with org.wso2.carbon.identity.oauth inside [IS_HOME]\reposiroty\components\plugins

2. Copy following jars from OAUTH_SAMPLE\dropins to [IS_HOME]\reposiroty\components\dropins
org.wso2.carbon.identity.oauth-3.2.1.jar
org.wso2.carbon.identity.oauth.stub-3.2.1.jar
org.wso2.carbon.identity.oauth.ui-3.2.1.jar

3. Above [1] & [2] steps are not required when OAuth 3.2.1 feature is available in WSO2 feature repo - you can simply point there and update.

4. Start WSO2 Identity Server

5. Login as admin/admin and go to OAuth and register a consumer application. When creating the application make sure you give http://localhost:9767/playground/oauth/oauth_callback as the callback url. This is the location we are going to setup our sample web app later.

6. Also - once created the app - click on the link under you application name - there you can see the corresponding consumer key and the consumer secret for your app.


7. Now we need to setup the XACML engine in WSO2 Identity Server

9. Go to Entitlement --> Administration --> Import Policy --> Select file system and import the policy OAUTH_SAMPLE/xacml.policy

10. Once imported - make sure you click on the ENABLE link against the imported policy.

11. That completes the Identity Server setup.

Now, let's setup WSO2 ESB.

1. Unzip the downloaded copy of WSO2 ESB and remove all jars starting with org.wso2.carbon.identity.oauth inside [ESB_HOME]\reposiroty\components\plugins

2. Copy following jars from OAUTH_SAMPLE\dropins to [ESB_HOME]\reposiroty\components\dropins
org.wso2.carbon.identity.oauth.mediator-3.2.1.jar
org.wso2.carbon.identity.oauth.stub-3.2.1.jar

3. Above [1] & [2] steps are not required when OAuth 3.2.1 feature is available in WSO2 feature repo - you can simply point there and update.

4. Open ESB_HOME\repository\conf\carbon.xml and find for the element Offset and set it to 2.
This will make sure that ESB starts on ports 9445/9765.

5. Start WSO2 ESB

6. Login as admin/admin and replace the synapse configuration in the source view - with the content from OAUTH_SAMPLE\synapse.xml

7. That's it and we are done with the ESB.

Let's set up the sample web app with WSO2 Application Server.

1. Open AS_HOME\repository\conf\carbon.xml and find for the element Offset and set it to 4.
This will make sure that App Server starts on ports 9447/9767.

2. Copy OAUTH_SAMPLE\playground.war to AS_HOME\repository\deployment\server\webapps

3. Start WSO2 Application Server

Now let's see how web app works.

1. Go to http://localhost:9767/playground


2. To get the request token, type your consumer key and consumer secret corresponding to your registered oauth application. Set the scope as echoService [should be the exact name, since that is what is been referred in the XACML policy].

3. Once you get the request token, you need to get that authorized by the user.

4. After that you can exchange the authorized token to an access token.

5. Copy the value of oauth_token from the response to [4] - we need this value when we are going to access the resource.

Now let's try to invoke a service with the obtained access token. Following java code explains how to do that. You need replace the values of CONSUMER_SECRET,CONSUMER_KEY and OAUTH_TOKEN. The value of OAUTH_TOKEN is the one you got with the access token.
package org.wso2.rest.security.oauth;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

import com.google.gdata.client.GoogleService;
import com.google.gdata.client.Service.GDataRequest;
import com.google.gdata.client.authn.oauth.GoogleOAuthParameters;
import com.google.gdata.client.authn.oauth.OAuthHmacSha1Signer;

public class OauthClient {

 private static final String ESB = "http://127.0.0.1:8282/";

 /**
  * @param args
  */
 public static void main(String[] args) {

  final String CONSUMER_SECRET = "9FXwlWNQdUlG2rWk7os3VRz8dfsa";
  final String CONSUMER_KEY = "yumx9s1HAf1iaItr1UZw4afEEjga";
  final String OAUTH_TOKEN = "hfiYq1ppu3VhLsFWxpFjCUDc3Jwa";

  GDataRequest request = null;

  try {

   GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
   oauthParameters.setOAuthConsumerKey(CONSUMER_KEY);
   oauthParameters.setOAuthConsumerSecret(CONSUMER_SECRET);
   oauthParameters.setOAuthToken(OAUTH_TOKEN);

   OAuthHmacSha1Signer signer = new OAuthHmacSha1Signer();
   GoogleService service = new GoogleService("demoservice", "myapp");
   service.setOAuthCredentials(oauthParameters, signer);
   String param = "hi";
   String baseString = ESB + "services/oauth_proxy/echoString" + "?xoauth_requestor_id="
     + CONSUMER_KEY + "&in=" + param + "&scope=echoService";
   URL feedUrl = new URL(baseString);
   request = service.createFeedRequest(feedUrl);
   request.execute();
   System.out.println(convertStreamToString(request.getResponseStream()));
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 private static String convertStreamToString(InputStream is) throws IOException {
  if (is != null) {
   StringBuilder sb = new StringBuilder();
   String line;
   try {
    BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
    while ((line = reader.readLine()) != null) {
     sb.append(line).append("\n");
    }
   } finally {
    is.close();
   }
   return sb.toString();
  } else {
   return "";
  }
 }

}

To run the above client you need to have google-collect and gdata-core jars in your classpath.