Enterprise Integration Zone is brought to you in partnership with:

Ross founded the open source Mule® project in 2003. Frustrated by integration "donkey work," he set out to create a new platform that emphasized ease of development and re-use of components. He started the Mule project to bring a modern approach, one of assembly, rather than repetitive coding, to developers worldwide. He is now the Founder and CTO of Mulesoft. Ross is a DZone MVB and is not an employee of DZone and has posted 91 posts at DZone. You can read more from them at their website. View Full User Profile

API Manager – Simple Java Client Access Example

06.09.2014
| 3633 views |
  • submit to reddit

 [This article was originally written by Jeff Schenk.]

I recently had a customer wanting to build a simple UI to maintain additional filtering data associated to a defined “Contract” contained within API Manager. This code would have to run outside of the MuleSoft eco-system, as a service, within a JAVA Data Layer container environment.

My goal was to develop a very simple JAVA API Manager Client Access Example, whose concept prototype could be used as a basis to construct a necessary Mashup of API Manager Resources and Custom Client oriented resources. A primary emphasis is to understand the OAUTH2 Authentication exchange requirements.

Requirements

API Manager

To begin you can review the API Manager Console located at https://anypoint.mulesoft.com/api-platform/api/console/#

Here we can see all of the available protected resources available from API Manager’s REST API.

You can drill down as well as request Authentication using your API Manager account credentials to perform the related resource queries.

But our goal is to provide a programmatic way of accessing API Manager resources. Any programming language can be used. In this demonstration, I am using JAVA. The whole idea around RESTful API’s is to eliminate lock in and be language agnostic. So API’s are our bridges to the world around.   Hmm, sounds like another blog…

One major requirement is that where ever your client will be running, it must be able to access API Manager via SSL and the default port of 443. This is a hardened requirement and facility to provide secure access to API Manager, as it is one of the components within the MuleSoft Anypoint eco-system of products.

Reviewing OAUTH2

First, I wanted to refresh myself on OAUTH2 and the handshake performed among the parties involved.  Reviewing the OAUTH V2 specification located at: http://tools.ietf.org/html/draft-ietf-oauth-v2-31, provided me with the necessary information.  Always good to review the specification, but in the end there can be nuances distinctive to the provider. In summary of the specification, upon sending our credentials and being authenticated on the provider side, we shall receive an “access_token” contained within the Location header of the HTTP Resource to our authentication request.

However, the most important part of developing a correct Authorize request is to specify the proper parameters, per the provider, to send on our HTTP POST request to API Manager’s Authorize resource, “/authorize“.

The Authorize request parameters we must use are as follows:

  • grant_type:

Required OAUTH2 grant Type, to indicate a user name and password will be supplied.
Valuepassword

  • client_id:

Required, Provides Client Identifier, specific to API Manager to indicate client context, if not specified, you will receive an error indicating “invalid_request No client identification nor authentication found”.
ValueCONSOLE

  • response_type:

Required, Indicate our Request and Response Type.
Valuetoken

  • redirect_uri:

Required and encoded, Indicate the Redirect URI, which will be received in our Location Header upon redirect response.
Valuehttps%3A//anypoint.mulesoft.com/api-platform/api/console/

  • scope:

Required and encoded, The authorization and token endpoints allow the client to specify the scope of the access request using the “scope” request parameter. In turn, the authorization server uses the encoded “scope” response parameter to inform the client of the scope of the access token issued.API Manager will determine access right based upon the scope setting. In our example, we are requesting full access.
Value(s): Specified as a concatenated String Value separated using an encoded space character of “%20“, as in “READ_SERVICES%20CONSUME_SERVICES…”

  • ADMIN_ORGANIZATIONS
  • READ_SERVICES
  • WRITE_SERVICES
  • CONSUME_SERVICES
  • APPLY_POLICIES
  • READ_CONSUMERS
  • WRITE_CONSUMERS
  • CONTRACT_MGMT
  • CONSUME_POLICIES
  • username:

Required API Manager Account Principal
ValueYour API Manager Account Principal

  • password:

Required API Manager Account Credentials
ValueYour API Manager Account Credentials

JAVA Client

The current JAVA Source code for this project can be found publicly on Github at: https://github.com/mulesoft-consulting/apimanager-oauth2-client.

Class Diagram of our Classes in project

Very simple JAVA Class organization where we have an Interface, which contains all of our necessary constants defined.  A Main class, to demonstrate the Authentication and then subsequent access of a protected resource.  A Static Tool class, to provide the “Authentication” and “GetResource” methods called by our Main class.  And finally two POJOs, which will represent our Authentication and Resource Result objects respectfully.

 
 
 
This JAVA gist, provides details on the client side Authorize request:

  	// Assuming HttpClient instantiated, see APIManagerClientTools for full Source.
  
   	String resource = "https://anypoint.mulesoft.com/api-platform/api" + "/authorize";

    	// Initialize the HTTP Port End Point.
	HttpPost httpPost = new HttpPost(resource);

	// Build Name Value Pair Parameters for POST Request.
	List<NameValuePair> nvps = new ArrayList<NameValuePair>();
	nvps.add(new BasicNameValuePair("grant_type", "password"));
	nvps.add(new BasicNameValuePair("client_id", "CONSOLE"));
	nvps.add(new BasicNameValuePair("response_type", "token"));
	nvps.add(new BasicNameValuePair("redirect_uri", REDIRECT_URI));
		
	// Set Scopes Accordingly.
	nvps.add(new BasicNameValuePair("scope", API_MANAGER_SCOPES));

	// Add the Basic Authentication for API Manager Principal and Credentials.
	nvps.add(new BasicNameValuePair("username", username));
	nvps.add(new BasicNameValuePair("password", password));

	// Associate the Parameters to the Post Request.
	httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
	// Issue Post to Authenticate and Obtain our Access Token.
	HttpResponse response = httpClient.execute(httpPost);
	
	// Should receive a Response Status Code of 302 indicating a Redirect and 
	// the Location Header will contain our access_token if authenticated correctly.

		// TODO Throw a RunTime Exception
		if (response.getStatusLine().getStatusCode() != 302) {
			log.error("Error Expecting a 302 redirect, but found: "
					+ response.getStatusLine()
					+ " Content Length:"
					+ ((response.getEntity() != null) ? response.getEntity()
							.getContentLength() : "null"));
			for (Header header : response.getAllHeaders()) {
				log.info("  Header: " + header.getName() + ": "
						+ header.getValue());
			}
			return null;
		}
		// Obtain the Location Header, which has been set per our 302 response
		// Redirect.
		// We still need to verify that we have been authenticated,
		// by the presence of the access_token or not.
		Header locationHeader = response.getLastHeader("Location");
		if (locationHeader == null) {
			return null;
		}
		return new APIManagerAuthenticationResult(locationHeader.getValue());

Upon receiving the response from the “/authorize” Post request, you should receive a status code of 302.  Which indicates a redirection.  You now interrogate the “Location” HTTP Header to obtain our access_token upon successful authentication or obtain an error condition.  Ensure you specify the “client_id” parameter with a value of “CONSOLE“, one of those undocumented gotchas.  If you do not specify, you will receive an error condition.  And you will possibly be left scratching/banging your head for an hour and a day or so, trying to understand what is wrong with the request.

Once you have the access_token, in this example, we use the JAVA constructor for APIManagerAuthenticationResult to parse the Location Header returned from our “/authorize” request and instantiate the POJO for use in upstream layers to easily access the access_token for use in subsequent API Manager REST API calls.

This JAVA gist, provides details on the client side Get Resource request:

		// Access A protected Resource....
		// Set Parameters based upon Resource Request.
		String fullyQualifiedResource = API_ENDPOINT + resource + "?"
				+ ACCESS_TOKEN + "=" + accessToken;
		if ((parameters != null) && (!parameters.isEmpty())) {
			if (!parameters.startsWith("&")) {
				fullyQualifiedResource = fullyQualifiedResource.concat("&");
			}
			fullyQualifiedResource = fullyQualifiedResource.concat(parameters);
		}
		// Instantiate the HTTP Get Request
		HttpGet getRequest = new HttpGet(fullyQualifiedResource);
		// Set our Content to Accept, either XML or the default of JSON.
		if ((responseContent != null)
				&& (responseContent.equalsIgnoreCase("xml"))) {
			getRequest.addHeader("accept", API_MANAGER_CONTENT_XML);
		} else {
			getRequest.addHeader("accept", API_MANAGER_CONTENT_JSON);
		}
		// Execute the Get Request
		HttpResponse response = httpClient.execute(getRequest);
		// Build up the Response Object.
		APIManagerResourceResult apiManagerResourceResult = new APIManagerResourceResult(
				resource, response.getStatusLine().getStatusCode());
		// Pull the Data in as Native String Data.
		// Here we simply pull the Requested Content Data as String, but can easily be
		// Transformed to Native JSON, XML or JAVA POJO per your requirements.
		// Use the API Manager API Console to provide insight into responses from
		// various resource Requests.
		BufferedReader br = new BufferedReader(new InputStreamReader(
				(response.getEntity().getContent())));
		StringBuffer sb = new StringBuffer();
		String output;
		while ((output = br.readLine()) != null) {
			sb.append(output);
		}
		// Set the Response Data.
		apiManagerResourceResult.setData(sb.toString());
		// return the Result Object.
		return apiManagerResourceResult;

You should receive a status code of 200 from a resource Get Request.  You may however, receive, a 403, indicating a Forbidden request.  Depending upon your request, the 403 will indicate that based upon the specified authorization scopes present and specified, the current user principal does not have access to the requested resource.  You should review API Manager user your are using as well as the scope specified to resource requested.

Running

Once you have all the required items and have built the source code, you will be able to run the demonstration.

Running the example will perform:

  • Authentication of supplied credentials to API Manager
  • Obtain an access_token
  • Using the acquired access_token, Perform rudimentary get requests for each of the authenticated principal’s API Manager resources.

To run from command line using Maven perform the following command substituting your Credentials:

mvn exec:java -Dexec.mainClass="org.mulesoft.apimanager.client.APIManagerClient" \
              -Dexec.classpathScope=runtime \
              -Dexec.args="arg0 arg1"

Where:

  • arg0 is your API Manager Account Principal
  • arg1 is your API Manager Account Credentials

Here is abridged example log of a run:

May 28, 2014 1:46:31 PM org.mulesoft.apimanager.client.APIManagerClient main
INFO: Access MuleSoft Anypoint API Manager via Account Principal: <YOUR API MANAGER USER PRINCIPAL>
May 28, 2014 1:46:35 PM org.mulesoft.apimanager.client.APIManagerClient reportResult
INFO: Resource Request: /organizations/current Status: 200 Data Length: 106 Data:[{"name":"Jeff Schenk Org","creat ... ]
May 28, 2014 1:46:37 PM org.mulesoft.apimanager.client.APIManagerClient reportResult
INFO: Resource Request: /services Status: 200 Data Length: 2755 Data:[{"count":3,"limit":10,"offset":0 ... ]
May 28, 2014 1:46:37 PM org.mulesoft.apimanager.client.APIManagerClient reportResult
INFO: Resource Request: /policies Status: 200 Data Length: 1574 Data:[{"policies":[{"id":"53713ba3e4b0 ... ]
May 28, 2014 1:46:37 PM org.mulesoft.apimanager.client.APIManagerClient reportResult
INFO: Resource Request: /announcements Status: 200 Data Length: 171 Data:[{"announcements":[],"links":[{"r ... ]
May 28, 2014 1:46:37 PM org.mulesoft.apimanager.client.APIManagerClient reportResult
INFO: Resource Request: /policy-templates Status: 200 Data Length: 7103 Data:[{"policyTemplates":[{"name":"OAu ... ]
May 28, 2014 1:46:38 PM org.mulesoft.apimanager.client.APIManagerClient reportResult
INFO: Resource Request: /consumers Status: 200 Data Length: 2801 Data:[{"consumers":[{"id":"gfs-alerttr ... ]
May 28, 2014 1:46:38 PM org.mulesoft.apimanager.client.APIManagerClient reportResult
INFO: Resource Request: /contracts Status: 200 Data Length: 2592 Data:[{"contracts":[{"id":"53715027e4b ... ]
May 28, 2014 1:46:39 PM org.mulesoft.apimanager.client.APIManagerClient reportResult
INFO: Resource Request: /taxonomies Status: 200 Data Length: 935 Data:[{"taxonomies":[{"id":"gfs-corpor ... ]
May 28, 2014 1:46:39 PM org.mulesoft.apimanager.client.APIManagerClient reportResult
INFO: Resource Request: /tags Status: 200 Data Length: 132 Data:[{"count":0,"limit":10,"offset":0 ... ]
May 28, 2014 1:46:39 PM org.mulesoft.apimanager.client.APIManagerClient reportResult
INFO: Resource Request: /agent-tokens Status: 200 Data Length: 2062 Data:[{"agentTokens":[{"agentToken":"e ... ]
May 28, 2014 1:46:40 PM org.mulesoft.apimanager.client.APIManagerClient reportResult
INFO: Resource Request: /environments Status: 200 Data Length: 1641 Data:[{"count":5,"limit":10,"offset":0 ... ]
May 28, 2014 1:46:41 PM org.mulesoft.apimanager.client.APIManagerClient reportResult
INFO: Resource Request: /users Status: 200 Data Length: 1453 Data:[{"count":5,"limit":10,"offset":0 ... ]
May 28, 2014 1:46:42 PM org.mulesoft.apimanager.client.APIManagerClient reportResult
INFO: Resource Request: /users Status: 200 Data Length: 1193 Data:[<?xml version="1.0" encoding="UT ... ]
May 28, 2014 1:46:42 PM org.mulesoft.apimanager.client.APIManagerClient main
INFO: 
Done

In Summary

Using this very simple example, you should be able to evolve your own Client specific to your needs, in your preferred Lingua Franca, to incorporate and Mash-In API Manager resources with your existing Enterprise Application Processed and Resources providing seamless integration.

Published at DZone with permission of Ross Mason, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)