Saturday, September 15, 2012

Security Patterns - Direct Authentication & Role Based Access Control

Authentication and authorization are vital aspects of any secured system or service which expose business assets to outside. Authentication itself is not sufficient when you want to restrict access to different resources for different types of authenticated users.

There are different authentication and authorization patterns.

In this post we will look at how to implement direct authentication and role based access control.

Direct Authentication
In direct authentication, clients share their credentials with server through a trust relationship established prior to the actual service invocation - eg: during user registration.
And when the client accesses the secured service, provided credentials are validated against the ones stored in the user store.
We call this direct authentication since the server itself stores client's credentials and validates them at authentication.

Role Based Access Control
Authorization models have evolved over time. In role based access control, users are assigned to a particular role and the permissions to that role. This is scalable than user-centric permission model where permissions are assigned per user, but coarse grained and coupled with application code as opposed to policy based access control which we'll look at in a future post.

Let us secure a service with above security mechanisms using WSO2 open source Enterprise Service Bus (ESB).

Overview
Before taking you through the steps, following is the architecture diagram of our solution.


- BE Service which exposes the actual business logic is fronted by a proxy service in ESB so that BE service is not exposed to out side directly and also we can enforce all the QoS, auditing, necessary transformation at ESB in this way.

- Proxy service is secured using Web Service Security mechanism to require a UserName Token(containing user name, password of the user) to authenticate the user and RBAC to authorize the user before invoking the BE service.

- User credentials are stored in Active Directory user store connected to ESB.

 Steps:
1.Download and extract latest ESB pack from here.

2.Configure Active Directory as User Store : locate user-mgt.xml file from [ESB_Home]/repository/conf and enable the ActiveDirectoryUserStoreManager element and provide appropriate information to connect to AD in your domain. (WSO2 products can be integrated with heterogeneous user stores and you can connect to any user store that you prefer.)

3.Start the server and access the management console from the browser: https://localhost:9443/carbon and login with credentials : admin, admin.

4.BE Service : Echo Service in ESB will serve as the BE service in our above deployment. Obtain its url(http://localhost:8280/services/echo) and wsdl(http://localhost/services/echo?wsdl) which will be used to create the proxy service.


5. Proxy Service: From left hand panel, select "Services->Add->Proxy Services" and create a pass through proxy with name "SecuredEchoProxy", url and publish wsdl url with the ones obtained in the previous option.

6. Applying Security: Go to the proxy service's dash board like the one shown in above image and select "Security" under Quality of Service Configuration.

Enforcing Authentication:

- select enable security -> yes
- select the WS-Security mechanism we are going to apply -> Username Token

Enforcing Authorization:

- Click Next.
- Select which Roles are authorized to access this resource.


- Finish applying security.

You can invoke the proxy service from SOAP UI client or a java client with different user names belonging to different roles and test.

I have attached a maven project here with a java client which can invoke a service secured with UserName Token security policy.

UserName Token Security Policy:

    
        
            
                
                    
                        
                            
                        
                    
                    
                        
                            
                        
                    
                    
                        
                            
                        
                    
                    
                
            
            
                
                    
                
            
            
        
    


Message Communication:
Request:

   
      
         
            2012-09-15T12:21:11.203Z
            2012-09-15T12:26:11.203Z
         
         
            admin
            admin
         
      
      https://localhost:8243/services/SecuredEchoProxy 
      urn:uuid:a205c52e-0d22-465b-87c4-8192de4e3cbc
      urn:echoInt
   
   
      
         1
      
   


Response:
   
      
         
            
               2012-09-15T12:21:11.824Z
               2012-09-15T12:26:11.824Z
            
         
         urn:uuid:6ece26cd-e349-4246-9481-7b05f6d928c1
         urn:echoIntResponse
         urn:uuid:a205c52e-0d22-465b-87c4-8192de4e3cbc
      
      
         
            1
         
      
   
Remarks:
1. Request message contains user name and password of the user according to the UserName Token profile of WS-Security. Since password is sent in plain text, the security policy enforces a transport binding which requires HTTPS to be used in message communication to provide confidentiality at transport level.

2. As security policy requires, both request and response contains timestamp values to avoid replay attacks.

3. Rampart is used as the underlying SOAP security processing module. In the security policy shown above, rampart specific configuration is commented out for the  purpose of clarity.

1 comment:

  1. Hi,
    I did exactly the way described but it seems that the loadPolicy methods is throwing the following exceptions

    Exception in thread "main" java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
    at org.apache.neethi.AssertionBuilderFactoryImpl.findAssertionBuilderTarget(AssertionBuilderFactoryImpl.java:145)
    at org.apache.neethi.AssertionBuilderFactoryImpl.invokeBuilder(AssertionBuilderFactoryImpl.java:134)
    at org.apache.neethi.AssertionBuilderFactoryImpl.build(AssertionBuilderFactoryImpl.java:117)
    at org.apache.neethi.PolicyBuilder.processOperationElement(PolicyBuilder.java:224)
    at org.apache.neethi.PolicyBuilder.getAllOperator(PolicyBuilder.java:184)
    at org.apache.neethi.PolicyBuilder.processOperationElement(PolicyBuilder.java:217)
    at org.apache.neethi.PolicyBuilder.getExactlyOneOperator(PolicyBuilder.java:180)
    at org.apache.neethi.PolicyBuilder.processOperationElement(PolicyBuilder.java:215)
    at org.apache.neethi.PolicyBuilder.getPolicyOperator(PolicyBuilder.java:174)
    at org.apache.neethi.PolicyBuilder.getPolicy(PolicyBuilder.java:124)
    at org.apache.neethi.PolicyEngine.getPolicy(PolicyEngine.java:100)
    at com.pmi.service.UTClient.loadPolicy(UTClient.java:114)
    at com.pmi.service.UTClient.main(UTClient.java:84)
    Java Result: 1

    ReplyDelete

Note: Only a member of this blog may post a comment.