Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

This document is a  brief description of the processing that occurs to authenticate and authorize an HTTP request using Acegi and the SAIS Framework.

There are two parts to this. One part is performed by Acegi, and the other part is performed by SAIS framework code.

Acegi

Acegi is a package that tries to abstract authentication and authorization processing in a manner that allows them to be customized for a particular set of requirements. For web applications, Acegi is "plugged in" as a servlet filter. If the Acegi servlet filter is configured in the web.xml then Acegi will be called on each request to the servlet.

Acegi processing is composed of parts that are assembled into what is called a "filter chain". Those parts are themselves customized by injection of service beans. The filters in an Acegi filter chain are not the same as servlet filters, although the general concept is the same. The filter chain determines The HTTP request is intercepted in a servlet filter, that delegates to a collection of Acegi filters, called the filter chain. The filter chain ensures the sequence of authorization and authentication processing, and manages authentication protocols and access to security information about users. Upon successful authentication and authorization it establishes a SecurityContext for use by the application.the inclusion of authentication protocols.

The end result of running the filter chain is that access is either granted or denied to the url requested. Granted access creates an Acegi Security Context for the request, which an application may consult for roles and user information collected previously during the Acegi processing.  Denied access should cause an access denied message to be returned to the user.

SAIS Framework

The SAIS framework provides a wrapper around Acegi, so that applications are not directly tied to a particular security framework implementation. It also provides services to the Acegi filter chain that handle the specifics of authentication and authorization as are customary or required at MIT. For example, it provides services for SSO authentication, and MIT Roles database, student role, instructor role, MITSIS STV_ROLES, and MITSIS STVACC roles authorizations separately or in combination. It also provides an impersonation function that is safer than MITSIS kerberos manipulation impersonation. Additional authorization schema may be plugged in using the SAIS framework so that Acegi will consult them in its processing, if needed.

It also provides local development environments a way to test different roles and users with an application.

The Filter Chain Proxy and the Acegi filters

Complexity is the price of flexibility. There are several interacting system artifacts, the components and their configurations.

Acegi itself and the SAIS framework components are all configured using the Spring context. Configurations for Acegi and framework components related to it are found in the The filter chain is configured in the Spring Context, the servlet filter in web.xml. SAIS applications will use either Spring Context configurations for security will be in either applicationContext-common-security.xml of an application or in SAIS Common. Some configuration entries in web.xml and applicationContext-web.xml , located in src/main/resources of the applicationare also important.

The configuration bean for the filter chain is called the filterChainProxy. Here is a sample configuration:

Code Block
 <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
		<property name="filterInvocationDefinitionSource">
			<value>
				PATTERN_TYPE_APACHE_ANT
				/css/**=#NONE#
				/dhtml/**=#NONE#
				/images/**=#NONE#
				/js/**=#NONE#
				/**=httpSessionContextIntegrationFilter,ssoAuthenticationProcessingFilter,basicAuthenticationProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor
			</value>
		</property>
	</bean>

...

In this example,

  1. We are telling the filter chain to run, that is authenticate and authorize, on url patterns that match everything except the contents of /images and /js.
  2. We are constructing the filter chain components processing order. The components are references to beans defined in the Spring context.

The beans in this example serve order is defined on the line starting with "/**=httpSessionContextIntegrationFilter".  The items in this list are also configured bean references. They perform the following functions :

httpSessionContextIntegrationFilter: Gets an existing security context from the HTTP session, or creates a new empty context.

ssoAuthenticationProcessingFilter: If authentication has not already been established in the SecurityContext ( that is, was not present in the session ), checks to see if the user is already set in the servlet request, indicating that SSO has authenticated the user.  If so, it sets up all the data structures needed by the security context. This includes the list of roles that the user is authorized for, based on the results of calling the configured authorization services ( see below ).

basicAuthenticationProcessingFilter: If authentication has not already been established ( that is by either being present in the session or by SSO ), and the local.authentication property has been set, performs HTTP Basic authentication. The user is prompted for a username and password, which must match what is configured in the application property file.  This filter is intended as a solution to running the application with a security context in the absence of SSO, which is the situation on developer's local workstations. This filter checks that the user and password entered in the login prompt in the browser match the property values for Local Authentication Properties. It then sets up all the data structures needed by the security context. This includes the list of roles that the user is authorized for, based on the results of calling the configured authorization services ( see below ).

code
Panel

Local Authentication Properties: A set of standard properties that tell the security framework. The following properties are used for local authentication.

local.authentication=true
local.user.name=sabrown
local.user.password=whatever

All of these properties must be present.  The local authentication properties should never be set on SAIS servers.
They are set in the Application Property File that resides in the user's home folder.

exceptionTranslationFilter: catches all exceptions from the filters that follow. Applies configured exception handlers based on the exception type caught. For example, if an AuthenticationException is thrown, indicating that the request is not authenticated yet, then it calls the method to start the authentication process.  If an AccessDeniedException is thrown, indicating that authentication has failedthe user is not authorized, then the AccessDeniedHandler is called. The default handler simply sends an access denies http response code in the response header.

filterSecurityInterceptor: Secures the requested HTTP resource(s) based on the SecurityContext. The work is delegated to a number of helpers configured for this bean. Requires a definition of what resources are to be protected and what roles apply. If the requested resource is supposed to be protected and there is no established authentication in the SecurityContext by this point, it throws an AuthenticationException which is handled as described before.  Otherwise, it will determine if authorization in the SecurityContext is sufficient for access to the resource, throwing AccessDeniedException if appropriate. 

switchProcessingUserFilter: This is an optional filter that the allows a user to invoke a URL that lets them impersonate another user. Since access to this feature usually requires that the request be authorized for the URL resource that performs the switch, it follows the filterSecurityInterceptor in the chain. Once the switch is performed, the SecurityContext contains the credentials for a different user, but it also remembers the original user so impersonation may be exited and the original credentials restored.

There are several other filters in the SAIS framework.

The Authorization framework

As mentioned above, filters that authenticate users also get the "details" for the authenticated user, that is, the user's authorizations, to put into the security context. In the SAIS framework, there is a single bean that is configured to get the user details, the MitsisRolesUserDetailsService.

Here is a sample configurationThe beans that determines which authorization services will be called to get the authenticated user's roles looks as follows:

Code Block
 	<bean id="mitsisRolesUserDetailsService" class="edu.mit.common.security.acegi.userdetails.MitsisRolesUserDetailsService">
		<property name="authorizationService"  ref="authorizationService" />
	</bean>

	<bean id="authorizationService" class="edu.mit.common.security.authorization.MultipleAuthorizationsService">
		<property name="combine" value="false" />
		<property name="authorizationServices">
			<list>
				<ref bean="studentRoleAuthorizationService" />
				<ref bean="mitRolesAuthorizationService" />
			</list>
		</property>
	</bean>

The beans and property definitions in this example serve the following functions:

mitsisRolesUserDetailsService bean: acts as an adapter between the Acegi security system and the authorization classes in the SAIS framework.Basic Authentication: Acegi handles all

authorizationService bean: SAIS framework bean that implements the AuthorizationService interface. In this example, it is an implementation that delegates to a chain of other AuthorizationService implementations, one for determining if the user is a student, and another to obtain the roles the user may have in the MIT Roles database. The combine = false property means that roles from the two services will not be combined, that is, either the role student will be assigned to the user or the MIT roles, but not both. If combine = true the user would be assigned all roles found.

Application access to a user's roles in the Security Context

It is not uncommon for applications to need access to roles information that may be collected by Acegi and the SAIS framework.  The SAIS framework attempts to provide facilities to make this easier. Lets take the example of an application that needs to display a list of sections for the user to choose, which will allow them to view the students assigned to the section, and there is a rule that the class lists are only to be shown to instructors of the section.

First, we need to configure the authorization service to capture whether the user is an instructor.

Code Block

 <bean id="mitsisRolesUserDetailsService" class="edu.mit.common.security.acegi.userdetails.MitsisRolesUserDetailsService">
	<property name="authorizationService"  ref="authorizationService" />
 </bean>

 <bean id="authorizationService" class="edu.mit.common.security.authorization.InstructorAuthorizationsService">
        <property name="dao" ref="hibernateAuthorizedInstructorDao" />
 </bean>

The hibernateAuthorizedInstructorDao bean is defined in SAIS Common, which also defines a class AuthorizedInstructor and a hibernate mapping to it from the SFBRE_CURRENT_PERSON table.

The InstructorAuthorizationService has a single method, getAuthorizationsByUser. This method uses the dao to fetch the user's instructor records from MITSIS. These instructor records are wrapped in an InstructorRoleAuthorization object. All of this is done merely by creating the configuration above.

A little later in the application processing, we will have a list of sections, and we want to filter the list to only include those that the instructor has taught. Probably first you would want to check that the user is in fact an instructor, that is, has at least taught some section  at some time, and if not, perhaps show them a different page:

Code Block

boolean isInstructor = securityContextService.hasAnyRole(new String[] { InstructorRoleAuthorizarion.ROLE_INSTRUCTOR });
Impersonation

switchProcessingUserFilter: This is an optional filter that the allows a user to invoke a URL that lets them impersonate another user. Since access to this feature usually requires that the request be authorized for the URL resource that performs the switch, it follows the filterSecurityInterceptor in the chain. Once the switch is performed, the SecurityContext contains the credentials for a different user, but it also remembers the original user so impersonation may be exited and the original credentials restored.

Page level security

One may also configure a mapping of roles to page urls. In the example above where we were testing if a user had the instructor role before showing them a page to select sections to view, instead of writing code, we could have simple declared our protection like this:

Code Block

 	<bean id="filterSecurityInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
		<property name="authenticationManager" ref="authenticationManager"/>
		<property name="accessDecisionManager" ref="accessDecisionManager"/>
		<property name="objectDefinitionSource">
			<value>
				PATTERN_TYPE_APACHE_ANT
				/**=IS_AUTHENTICATED_FULLY
				/sections.html=ROLE_INSTRUCTOR
			</value>
		</property>
	</bean>

and the Acegi framework would have invoked the access denied handler when a user who did not have this role tried to access the page. We could write the access denied handler to show a page with a friendly message or perhaps redirect the user somewhere they are supposed to be the requirements of the Basic authentication protocol. It is a two step process. An unauthenticated request will result in a challenge response header sent to the browser that will result in the familiar ugly login box to the user. When the user submits the login credentials in what is now the second request, it contains a header with the credentials. The presence of this header is detected and processed by the basicAuthenticationProcessingFilterand the credentials are compared to the values from the application property file. If there is a match the data structures for the security context are configured including the list of roles from the configured authorization services. Since the first request does not contain the credentials header, it always falls through the filter chain to the filterSecurityInterceptor, which will throw an exception ( if the requested resource should be secured ), which is caught by the exceptionTranslationFilter, which in turn results in the challenge response being issued. You also may wonder, if there is now a second request required, what happened to the first one which actually has the resource you want to view ? It is temporarily stored in the session and then resumed if authentication and authorization succeed. So Acegi does a lot of work here that you normally do not have to worry about.