I have discussed about XACML Fine Grained Authorization and how we can use WSO2 IS as a XACML engine in the previous post, Providing XACML Fine Grained Authorization to WebApps : Using WSO2 Identity Server - Part 1 .
So as we know we can use WSO2 Application Server or Apache Tomcat or any other web container to host our web apps. So if there is a requirement to provide authorization to those web apps? That means some one want to allow access to there web apps on a fine grained manner. This has been done in the WSO2 platform. That was a project of mine. So using WSO2 Identity server as the XACML Policy Decision Point (PDP) we can provide fine grained authorization to webapps. This PDP can be access via a web service called Entitlement Service.
So what will the Policy Enforcement Point(PEP) for the webapp authorization ? After having some discussions we thought that a Servlet Filter will be the ideal solution. Any webapp developer can define a servlet filter which they want to use. Also we can use servlet filter in any kind of webapp container.
On that decision we have created a servlet filter which user can use to provide authorization to their web apps. We gave the name Entitlement Servlet Filter to that. It uses a Proxy to communicate with WSO2 Identity Server. The Entitlement PEP Proxy is responsible for following tasks,
- There is a service in the WSO2 IS called Entitlement Service, that service is used to evaluate XCAML requests.
- That is a admin service which can be used by the Admin Role.
- To use that service we have to log in to the IS using AuthenticationAdmin Service.
- So PEP Proxy log in to the IS as admin, so we can use it's Entitlement Service to evaluate requests coming.
- We provide following parameters to PEP Proxy to evaluate the request against XACML policies in the WSO2 IS, UserName, ResourceName, Action and Environment. So it queries IS using the provided parameters and gives us the authorization decision.
The following digram shows how the the servlet filter gets the authorization decision,
The next problem is how we should obtain the parameters, UserName, ResourceName, Action and Environment. Exept the user name others we have. Because they are all related tot the web app. How we can get the user name? For that we used J2EE authentication mechanisms,
- Basic Authentication
- Client Cert Authentication
- Digest Authentication
- Form Authentication
After the authentication we can obtain the username in the the servlet filter. So all the parameters are found now.
As shown in the digram, when a request comes to a particular weapp which has the engaged Entitlement Servlet Filter it obtains the parameters UserName, ResourceName, Action and Environment. Then it initialize the PEP Proxy to communicate with WSO2 IS. After that it send the parameters and get the Entitlement decision. On the provided decision it stop or pass the request which has came to the web app.
The next critical thing is how the user can engage the Entitlement Servlet Filter. For that we use the web.xml. The following shows a example web.xml which configures the Entitlement Servlet Filter.
From the following URL you can fine the Entitlement Servlet Filter. https://svn.wso2.org/repos/wso2/carbon/platform/trunk/components/identity/org.wso2.carbon.identity.entitlement.filter/
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <!-- Sample deployment descriptor configuration for EntitlementFilter --> <!-- The scope in which the subject would be available. Legal values are basicAuth,request-param, request-attribute, session --> <context-param> <param-name>subjectScope</param-name> <param-value>request-param</param-value> </context-param> <!-- The name of the identifier by which to identify the subject --> <context-param> <param-name>subjectAttributeName</param-name> <param-name>userName</param-name> </context-param> <!-- The username to perform EntitlementService query--> <context-param> <param-name>userName</param-name> <param-value>admin</param-value> </context-param> <!-- The password to perform EntitlementService query --> <context-param> <param-name>password</param-name> <param-value>admin</param-value> </context-param> <!-- The URL to perform EntitlementService query--> <context-param> <param-name>remoteServiceUrl</param-name> <param-value>https://localhost:9443/services</param-value> </context-param> <!-- EntitlementFilter Settings --> <filter> <filter-name>EntitlementFilter</filter-name> <filter-class>org.wso2.carbon.identity.entitlement.filter.EntitlementFilter</filter-class> <!-- Client class that extends AbstractEntitlementServiceClient. Legal values are basicAuth, soap and thrift. Default is 'thrift'. --> <init-param> <param-name>client</param-name> <param-value>basicAuth</param-value> </init-param> <!-- Decision caching at PEPProxy. Legal values are simple and carbon.This parameter is optional. If not specified no caching is done. --> <init-param> <param-name>cacheType</param-name> <param-value>simple</param-value> </init-param> <!-- Maximum number of cached entries. Legal values are between 0 and 10000 . Only works with caching. --> <init-param> <param-name>maxCacheEntries</param-name> <param-value>1000</param-value> </init-param> <!-- Time interval for which cached entry is valid. Only works with simple cache type. --> <init-param> <param-name>invalidationInterval</param-name> <param-value>100000</param-value> </init-param> <!-- URL ro redirect to if authorization fails --> <init-param> <param-name>authRedirectUrl</param-name> <param-value>/index.jsp</param-value> </init-param> <!-- Thrift host to be used if using 'thrift' client --> <init-param> <param-name>thriftHost</param-name> <param-value>localhost</param-value> </init-param> <!-- Thrift port to be used if using 'thrift' client --> <init-param> <param-name>thriftPort</param-name> <param-value>10500</param-value> </init-param> </filter> <!-- Filter mappings used to configure URLs that need to be authorized --> <filter-mapping> <filter-name>EntitlementFilter</filter-name> <url-pattern>/protected.jsp</url-pattern> </filter-mapping> <!-- Mandatory mapping that needs to be present to work with PEP cache update authorization--> <filter-mapping> <filter-name>EntitlementFilter</filter-name> <url-pattern>/updateCacheAuth.do</url-pattern> <dispatcher>FORWARD</dispatcher> </filter-mapping> <!-- EntitlementCacheUpdateServlet settings--> <servlet> <servlet-name>EntitlementCacheUpdateServlet</servlet-name> <servlet-class>org.wso2.carbon.identity.entitlement.filter.EntitlementCacheUpdateServlet </servlet-class> <!-- HTTPS port of the web container used when redirecting request to come over https port for cache update authentication --> <init-param> <param-name>httpsPort</param-name> <param-value>9453</param-value> </init-param> <!-- Authentication mode for cache update. Legal values are webapp and wso2is --> <init-param> <param-name>authentication</param-name> <param-value>webapp</param-value> </init-param> <!-- Authentication page used for cache update authentication. Legal values are default and custom --> <init-param> <param-name>authenticationPage</param-name> <param-value>default</param-value> </init-param> <!-- Authentication page URL used for cache update authentication. Works only with custom for authenticationPage --> <init-param> <param-name>authenticationPageUrl</param-name> <param-value>/updateCache.html</param-value> </init-param> </servlet> <!-- Servlet mapping needed for cache update authentication --> <servlet-mapping> <servlet-name>EntitlementCacheUpdateServlet</servlet-name> <url-pattern>/updateCache.do</url-pattern> </servlet-mapping> </web-app>