HTTPBC Authorization using Sun Java System Access Manager
Access Manager Authorization Architecture
Access Manager enables centralized authentication and policy evaluation services and dynamic access management control. In addition, enhanced manageability is achieved through a common user interface.
The most common deployment scenario for securing Web applications with Access Manager is through a Policy Agent-based architecture. In this architecture, you install a Policy Agent on the container that hosts the application and that acts as a policy enforcement point (PEP).
For securing open-esb application(using httpbc) with Access Manager the User only needs to configure the httpbc endpoint to enable authorization or policy enforcement point (PEP)
Fine-Grained Access-Level Authorization
The Access Manager Administrative Console (amconsole) is a Web-based interface for defining and managing policies for resources. This section describes how to set the authorization requirements by configuring the settings in the Administrative Console
By adopting the architecture described in the preceding section, you can configure, out of the box, the following two requirements:
- Access for all authenticated users
- Access, based on roles, to the application URI
Here is a summary of the procedure:
1. Create a Composite Application
2. Configure the http binding port to use the Authentication and Authorization Policy
3. Configure the access manager to create a Authorization Policy ( assuming a set of users already exist)
Creation of composite application project
- This assumes that the httpbc binding is configured for using Sun AccessManager see Athentication AM support
- create a new composite application using httpbc and bpel or can use this sample here
- Configure the policy in the wsdl to enable Authorization, note the attribute authorization="true" , by default this attribute is optional and its value is false
<service name="AuthAMService">
<port name="AuthAMPort" binding="tns:AuthAMBinding">
<soap:address location="http://localhost:${HttpDefaultPort}/AuthAMService/AuthAMPort"/>
<wsp:PolicyReference URI="#HttpAuthorizationBindingAMPolicy"/>
</port>
</service>
<wsp:Policy wsu:Id="HttpAuthorizationBindingAMPolicy">
<mysp:MustSupportBasicAuthentication on="true">
<!-- authenticationType is one of simple, am, or realm -->
<mysp:BasicAuthenticationDetail>
<mysp:AccessManager authorization="true"/>
</mysp:BasicAuthenticationDetail>
</mysp:MustSupportBasicAuthentication>
</wsp:Policy>
- If you run a client which invokes this webservices without configuring the access manager policy, you will see the following exception in the glassfish appserver log
com.sun.jbi.httpsoapbc.security.api.HttpBcSecurityException: com.sun.jbi.httpsoapbc.security.am.impl.AMAuthorizationException:
HTTPBC-E01031: UnAuthorized access to resource 'http://sbiswas-tecra.stc.com:9080/AuthAMService/AuthAMPort' by 'id=jondoe,ou=user,dc=sun,dc=com'
at com.sun.jbi.httpsoapbc.AbstractEndpoint.handleSecurity(AbstractEndpoint.java:586)
at com.sun.jbi.httpsoapbc.embedded.JAXWSGrizzlyRequestProcessor.processAsynchRequest(JAXWSGrizzlyRequestProcessor.java:353)
- Configure the the authorization policy for this application using the access-manager admin console,
- Create a new authorization policy using
- Access Control > Realm - sun > Realm - sun > New Policy
- Define the new rule based on the resource that is being accessed.
Important Note: the localhost is resolved using the InetAddress.getCanonicalHostName(), see the javadoc below, the api may not always return fully qualified domain name (FQDN) based on the system/dns/nis configuration. The best way to see what is the resolved name is to follow the authorization exception logging as specified above , in case the authorization fails because of mismatch in the user configured URL and the expected URL
InetAddress / public String getCanonicalHostName()
Javadoc/ Gets the fully qualified domain name for this IP address. Best effort method, meaning we may not be able to return the FQDN depending on the underlying system configuration.
- Configure the subject/s who can access this resource
- Once the policy configuration is complete, the glassfish appserver needs to be RESTARTED for the policy configuration to take effect
Invoke the webservice
sample client ,
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
/**
* @author Sujit Biswas
*
*/
public class AuthClient {
private static final String username = "jondoe";
private static final String password = "jondoe";
private Authenticator authenticator = new TestAuthenticator();
private class TestAuthenticator extends java.net.Authenticator {
public TestAuthenticator() {
setDefault(this);
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
}
public void testAccessManagerAuthorization() throws Exception {
Service service = Service.create(new QName("http://j2ee.netbeans.org/wsdl/AuthAM", "AuthAMService"));
QName echoPort = new QName("http://j2ee.netbeans.org/wsdl/AuthAM", "AuthAMPort");
String url = "http://localhost:9080/AuthAMService/AuthAMPort";
service.addPort(echoPort, null, url);
Dispatch<Source> dispatch = service.createDispatch(echoPort,
Source.class,
Service.Mode.PAYLOAD);
SOAPMessage outSoapMsg = MessageFactory.newInstance().createMessage();
// Build the message.
String request =
"<AuthAMOperation xmlns=\"http://j2ee.netbeans.org/wsdl/AuthAM\">" +
"<part1>hello</part1>" +
"</AuthAMOperation>";
final String expectedResponse =
"<?xml version=\"1.0\" ?>" +
"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
"<SOAP-ENV:Body>" +
"<m:AuthAMOperationResponse xmlns:m=\"http://j2ee.netbeans.org/wsdl/AuthAM\">" +
"<part1 xmlns:aut=\"http://j2ee.netbeans.org/wsdl/AuthAM\" xmlns:msgns=\"http://j2ee.netbeans.org/wsdl/AuthAM\" xmlns=\"\">hello</part1>" +
"</m:AuthAMOperationResponse>" +
"</SOAP-ENV:Body>" +
"</SOAP-ENV:Envelope>";
ByteArrayInputStream bais = new ByteArrayInputStream(request.getBytes());
Source input = new StreamSource(bais);
Source output = dispatch.invoke(input);
System.out.println ("After invoke");
assert (output != null);
StreamResult result = new StreamResult(new ByteArrayOutputStream());
Transformer trans = TransformerFactory.newInstance().newTransformer();
trans.transform(output, result);
ByteArrayOutputStream baos = (ByteArrayOutputStream) result.getOutputStream();
// Check the response content.
String responseContent = new String(baos.toByteArray());
System.out.println("Got response: \n" + responseContent + "\n");
assert (expectedResponse.equals(responseContent));
}
/**
* @param args
*/
public static void main(String[] args) {
try {
new AuthClient().testAccessManagerAuthorization();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}