Friday, 31 August 2012

Introduction to Spring Security Concepts

Spring security is a complex subject, with a steep learning curve. The purpose of this post is to try to reduce that learning curve and to be a reminder of the main security concepts every developers should master in order to configure security in Spring applications.

It is a not a substitute to reading the official documentation, especially the Spring security appendix describing the nuts and bolts of configuration elements. The Spring security 3 book is also helping connecting dots between concepts.

Facts

  • Authentication and Access Authorization – The main philosophy of Spring security is first to authenticate users, then to check their access credentials to resources. This is performed via a set of filters.
  • Annotation based configuration – So far, there is no such thing as Java based configuration with Spring security. Everything is based on XML configuration. You will not get rid of security.xml with Java programmatic configuration.
  • <servlet-name>-security.xml – One must specify the location of the security configuration XML file either in the contextConfigLocation parameter value (*) of web.xml or, if one uses configuration annotations, it can be imported with @ImportResource (**).
  • web.xml – One must configure the Spring security filter chain in the web.xml file (***) together with a filter mapping configuration to enable the Spring security.
  • Security Annotations - It is possible to enable JSR-250 annotations or Spring's @Secured annotations. Typically, these are used on services objects for access control.

Concepts

  • Auto-Config – A configuration element of the Spring Security namespace enabling (or not) the default configuration of Spring Security.
  • Access Decision Manager – Decides whether a user can access a resource or not.
  • Authentication Manager – It processes authentication requests via child authentication providers.
  • Authentication Provider – Depending on its accepted types of authentication requests, it processes them for approval or not.
  • Delegating Filter Proxy – A servlet filter capturing every user requests and sending them to the configured security filters to make sure access is authorized.
  • Principal – Represents anyone authenticated.
  • Provider Manager – An authentication manager instance processing authentication request through a list of authentication providers.
  • Security Context – A user's secured authenticated session. It is stored in a security context repository.
  • Session Authentication Strategy – Should a user have a session? Should we retrieve any existing ones? Should we automatically create one at each login? How many sessions can a user have? What about timeout? What's the strategy for session handling?

General Scheme

For a secured page, the general functional behavior of Spring security is the following:
  1. A user makes a request for a secured page.
  2. The configured Authentication Manager checks the user credentials.
  3. If necessary, the user provides them (for example, login and password).
  4. If the credentials are not validated successfully, access to the page is refused.
  5. The configured Access Decision Manager then makes sure the identified user has the right to access the page (i.e. has proper authority).
  6. If the authority is not established, access to the page is refused.
  7. Else, the page is displayed.

Security Filters

Every user requests pass through a set of filters. The Authentication Manager and the Access Decision Manager are both filters, functionally speaking. When auto-config is enabled, a set of defaut Spring security filters is automatically configured.

Here is how user queries are processed in more details:
  1. When a user makes a request, Spring loads its security context.
  2. If the user's request URL is the logout URL (by default /j_spring_security_logout), the user is logged out.
  3. If the user's request URL is an authentication form submission (by default  /j_spring_security_check), an attempt to authenticate the user is performed.
  4. If no login page is configured, a default login page is displayed (if the user is not authenticated yet).
  5. Checks whether the request has an Authorization header. If yes, user name and password is extracted for authentication. If authentication is successful, it is registered in the security context.
  6. Assuming a user was trying to access a page requiring authentication, this step retrieves the original request to that page, if the authentication is successful.
  7. The user request is wrapped together with the security context into a single object.
  8. If the user has not been authenticated successfully so far, it is flagged as anonymous.
  9. If the user has been authenticated, the session authentication strategy is applied. 
  10. Any AccessDeniedException and AuthenticationException thrown by any of the above are handled here.
  11. Delegation of authorization and access control decisions to an access decision manager.

Security Namespace

Spring security is defined in an XML document, just like maven configuration is defined in a pom.xml file. It has a namespace (i.e., a set of XML tag elements) which can be used to activate or configure Spring security features. Again, read the Spring security appendix to learn about these in details. It is a must to understand Spring Security.

Some of its main elements are:
  • <html auto-config='true'> - It is the parent element of web related configuration elements. It creates the filter chain proxy bean called springSecurityFilterChain for security. It has an auto-config attribute, which can be set to install the default Spring security configuration elements.
  • <access-denied-handler> - Can be used to set the default error page for access denials.
  • <intercept-url pattern="/**" access="ROLE_USER"> - This element creates a relationship between a set of URLs and the required access role to visit these pages.
  • requires-channel - This is an <intercept-url> attribute which can be used to require the usage of https to access a set of URLs (i.e., secured channels).
  • <form-login> - Can be used to define the login page URL, the URL for login processing, the target URL after login, the login failure URL, etc...
  • <remember-me> - If a user is not authenticated, and 'remembered' information about the user is available (for example, from a cookie), it will be used.
  • <session-management> and <concurrency-control> - To implement session management strategies.
  • <logout> - To configure the default logout page.
  • <http-firewall> - To implement a firewall filter.
  • <authentication-manager> - A required configuration element. It creates a provider manager. The child elements are <authentication-provider>.
  • <authentication-provider> - Can be used to create an in-memory authentication provider. The children <user-service> and <user> elements can be used to define user login-password combinations. Other types of authentication providers can be configured too.
  • <password-encoder> - If the users' login and password are stored in a database (for example), one can use this configuration element to specify how the password should be encrypted.

For a concrete Spring Security example, click here • More Spring related posts here.

REM: This blog does not cover all Spring Security features. Topics such as: password encryption, storage of credentials, 'Remember Me', SSL connections, sophisticated access control, OpenID, LDAP, Client Certificate Authentication in the Spring Security 3 book in details.

------------------------------------------------------------

(*)
<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
    /WEB-INF/myApp-security.xml
  </param-value>
</context-param>

(**)
@Configuration
@ImportResource("classpath:my/package/security.xml")
public class ApplicationConfig {

    // ...

}
(***)
<filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>