Tag Archives: Spring Security

Sample of Spring Security and CAS (Single Signon)

For people in hurry get the code from Github.

In continuation of my earlier blog on spring-test-mvc junit testing Spring Security layer with InMemoryDaoImpl, in this blog I will be doing the following,

  • Run a sample Jasig, deployed in tomcat instance
  • Run a sample Spring security Calendar application with uses single signon to do authentication and authorization of the application

Setup of Central Authorization Service (CAS): Jasig

Central Authorization Service (CAS) is a Single Signon application used to authenticate and authorize an application for centralized user access control. Jasig is an opensource CAS application. In order for Jasig to work we need to enable SSL.

<Connector SSLEnabled="true"
maxThreads="150"
port="8443"
protocol="HTTP/1.1"
scheme="https"
secure="true"
sslProtocol="TLS"
keystoreFile="${catalina.base}/conf/tomcat.keystore"
keystorePass="changeit"
truststoreFile="${catalina.base}/conf/tomcat.truststore"
trustStorePass="changeit"/>

Run the Calendar application against CAS

Build the code from spring-security-cas project using maven command “mvn clean package” and deploy the war file in the target folder into <Tomcat home>/webapps folder. Start the Tomcat instance. If you go to the calendar home page @ https://localhost:8443/calendar, you will see the webpage as below,

spring-security calendar application

spring-security calendar application

When you click on My Events we get the below Jasig page,

CAS jasig

CAS jasig

Enter login/password as user1@example.com/user1. You will get the access to your events.

When you log out, it will again redirect to Jasig logout page.

What is happening under the hood on Jasig side

Under the hood, Jasig CAS server is configured to work with inmemory LDAP as below,

<sec:ldap-server id="contextSource" ldif="classpath:ldif/calendar.ldif" root="dc=jbcpcalendar,dc=com" />

And mapping of LDAP attributes to CAS attributes happens in the below bean definition,

<!--
Bean that defines the attributes that a service may return.  This example uses the Stub/Mock version.  A real implementation
may go against a database or LDAP server.  The id should remain "attributeRepository" though.
-->
<bean id="attributeRepository">
<property name="contextSource" ref="contextSource"/>
<property name="requireAllQueryAttributes" value="true"/>
<property name="baseDN" value="ou=Users"/>
<property name="queryAttributeMapping">
<map>
<entry key="username" value="uid"/>
</map>
</property>
<property name="resultAttributeMapping">
<map>
<entry key="cn" value="FullName"/>
<entry key="sn" value="LastName"/>
<entry key="description" value="role"/>
</map>
</property>
</bean>

Check the deployerConfigContext.xml under webapp/WEB-INF folder in the project for more details

What is happening under the hood on Calendar application

In the web.xml we need to include a SingleSignon listener as below,

<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>

We need to define a casAuthProvider bean and include it in the authentication-manager in the security config as below,

<authentication-manager alias="authenticationManager">
<authentication-provider ref="casAuthProvider" />
</authentication-manager>

Refer src\main\webapp\WEB-INF\spring\security-cas.xml file for more details on casAuthProvider bean definition.

Maven dependency for Spring Security with CAS is as below,

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-cas</artifactId>
<version>3.1.0.RELEASE</version>
<scope>compile</scope>
</dependency>

I hope this blog helped you.

REFERENCE

Spring Security 3.1 by Robert Winch and Peter Mularien

Advertisements

spring-test-mvc junit testing Spring Security layer with Method level Security

For people in hurry get the code from Github.

In continuation of my earlier blog on spring-test-mvc junit testing Spring Security layer with InMemoryDaoImpl, in this blog I will discuss how to use achieve method level access control. Please follow the steps in this blog to setup spring-test-mvc and run the below test case.

mvn test -Dtest=com.example.springsecurity.web.controllers.SecurityControllerTest

The Junit test case looks as below,

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = WebContextLoader.class, value = { "classpath:/META-INF/spring/services.xml",
"classpath:/META-INF/spring/security.xml",
"classpath:/META-INF/spring/mvc-config.xml" })
public class SecurityControllerTest {

@Autowired
CalendarService calendarService;

@Test
public void testMyEvents() throws Exception {
Authentication auth = new UsernamePasswordAuthenticationToken("user1@example.com", "user1");
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(auth);

calendarService.findForUser(0);
SecurityContextHolder.clearContext();
}

@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void testForbiddenEvents() throws Exception {
calendarService.findForUser(0);
}
}
@Test(expected=AccessDeniedException.class)
public void testWrongUserEvents() throws Exception {
Authentication auth = new UsernamePasswordAuthenticationToken("user2@example.com", "user2");
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(auth);

calendarService.findForUser(0);
SecurityContextHolder.clearContext();
}

If you notice, if the user did not login or if the user is trying to access another users information it will throw an exception.

The interface access control is as below,

public interface CalendarService {

@PreAuthorize("hasRole('ROLE_ADMIN') or principal.id == #userId")
List<Event> findForUser(int userId);
}

The PreAuthorize only works on interface so that any implementation that implements this interface has this access control.

I hope this blog helps you. In my next blog I will explain how you integrate Spring Security with Central Authorization Service (CAS) Single Sign On.

REFERENCE

Spring Security 3.1 by Robert Winch and Peter Mularien

spring-test-mvc junit testing Spring Security layer with LDAP

For people in hurry get the code from Github.

In continuation of my earlier blog on spring-test-mvc junit testing Spring Security layer with InMemoryDaoImpl, in this blog I will discuss how to use Spring Security’s LDAP integration.

Please follow the steps in this blog to setup spring-test-mvc and run the below test case,

mvn clean test -Dtest=com.example.springsecurity.web.controllers.Video4LdapProviderControlerTest

The dependency required integrating LDAP is as below,

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
<version>3.1.0.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-protocol-ldap</artifactId>
<version>1.5.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.directory.shared</groupId>
<artifactId>shared-ldap</artifactId>
<version>0.9.15</version>
<scope>compile</scope>
</dependency>

In this example we used inmemory LDAP configured to work with calendar.ldif for all user/role information. In the real life, there will be a enterprise quality LDAP like Active Director configured with Spring Security. For configuring this in spring security configuration you need to add below code,

<ldap-server id="ldapServer" ldif="classpath:ldif/calendar.ldif" root="dc=jbcpcalendar,dc=com" />

The plumbing for spring-test-mvc to work with LDAP is in the class com.example.springsecurity.web.controllers.util.LdapSecurityRequestPostProcessors. The below code does the magic,

private UsernamePasswordAuthenticationToken authentication(ServletContext servletContext) {
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);

FilterBasedLdapUserSearch filterBasedLdapUserSearch = context.getBean(FilterBasedLdapUserSearch.class);

DirContextOperations ldapUserDetails = filterBasedLdapUserSearch.searchForUser(username);

List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(1);
authorities.add(new SimpleGrantedAuthority(ldapUserDetails.getStringAttribute("sn")));

return new UsernamePasswordAuthenticationToken(username, ldapUserDetails.getObjectAttribute("userpassword").toString(),
authorities);
}

spring bean definition for FilterBasedLdapUserSearch is as below,

<bean id="ldapSearch">
<constructor-arg value="ou=users"/> <!-- use-search-base -->
<constructor-arg value="(uid={0})"/> <!-- user-search-filter -->
<constructor-arg ref="ldapServer"/>
</bean>

I hope this blog helped. In my next blog I will be explaining how to integrate Spring Security with Method level access control.

REFERENCE

Spring Security 3.1 by Robert Winch and Peter Mularien

spring-test-mvc junit testing Spring Security layer with JdbcDaoImpl

In continuation of my earlier blog on spring-test-mvc junit testing Spring Security layer with InMemoryDaoImpl, in this blog I will discuss how to use Spring Security’s JdbcDaoImpl class.

In this blog, we will be discussing same usecase and same code base as in this blog, the only difference being for testing this feature you need to run different testcase as below,

mvn clean test -Dtest=com.example.springsecurity.web.controllers.Video3JdbcUserServiceControllerTest

The database schema for user authorization is as below,

create table calendar_users (
id bigint identity,
email varchar(256) not null unique,
password varchar(256) not null,
first_name varchar(256) not null,
last_name varchar(256) not null
);

create table calendar_user_authorities (
id bigint identity,
calendar_user bigint not null,
authority varchar(256) not null,
);

Below is the JDBC configuration to identify the user and his role/authorization to access.

<authentication-manager>
<authentication-provider>
<jdbc-user-service id="userDetailsService"
data-source-ref="dataSource"
users-by-username-query="select email,password,true from calendar_users where email = ?"
authorities-by-username-query="select cua.id, cua.authority from calendar_users cu, calendar_user_authorities cua where cu.email = ? and  cu.id = cua.calendar_user"/>
</authentication-provider>
</authentication-manager>

I hope this blog helped you. In my next blog, I will demo how to use LDAP for Securing an application.

REFERENCE

Spring Security 3.1 by Robert Winch and Peter Mularien

spring-test-mvc junit testing Spring Security layer with InMemoryDaoImpl

For people in hurry here is the code sample and the steps to setup the code.

Spring Security 3.1 is a framework that supports authentication and authorization in Java. Spring MVC has a good integration with Spring Security. In this blog, I will demonstrate how to JUnit test Spring Security layer for a Spring MVC application using spring-test-mvc.

The usecase we use in this blog is a Spring MVC based calendar application, where user can login and enter his events his events. User can see other user events but he cannot change it. An admin user can see other user’s Events as well as change it.

To enable spring-test-mvc, we need to setup spring-test-mvc. As a first setp get the latest code from github. and run the “mvn install” command in the downloaded folder. After that we need to add the below dependency in the pom.xml,

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test-mvc</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<scope>test</scope>
</dependency>

For a starter I will start writing the JUnit test as below to capture above usecase,

@Before
public void setup() {
mockMvc = MockMvcBuilders.webApplicationContextSetup(this.wac).addFilters(this.springSecurityFilterChain).build();
}

@Test
public void testIndex() throws Exception {
mockMvc.perform(get("/")).andExpect(status().isOk()).andExpect(forwardedUrl("/WEB-INF/views/index.jsp"));
}

@Test
public void testEventsNonAdmin() throws Exception {
mockMvc.perform(get("/events/").with(userDeatilsService("user1@example.com"))).andExpect(status().isForbidden());
}

@Test
public void testEventsAdminLogin() throws Exception {
mockMvc.perform(get("/events/").with(userDeatilsService("admin1@example.com"))).andExpect(status().isOk());
}

@Test
public void testMyEvents() throws Exception {
mockMvc.perform(get("/events/my").with(userDeatilsService("user1@example.com"))).andExpect(status().isOk());
}

@Test
public void testShow() throws Exception {
mockMvc.perform(get("/events/100").with(userDeatilsService("user1@example.com"))).andExpect(status().isOk());
}

@Test
public void testCreateEventForm() throws Exception {
mockMvc.perform(
post("/events/new").param("attendeeEmail", "user1@example.com").param("summary", "krishna").param("description", "whatever")
.param("when", "2012-01-01 01:02").with(userDeatilsService("user1@example.com"))).andExpect(status().isOk())
.andExpect(redirectedUrl("/events/my"));
}

To wire Spring Security with JUnit test you need to do as below,

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = WebContextLoader.class, value = {
"classpath:/META-INF/spring/video1-spring-inmemory-userdetailservice-config/services.xml",
"classpath:/META-INF/spring/video1-spring-inmemory-userdetailservice-config/security.xml",
"classpath:/META-INF/spring/video1-spring-inmemory-userdetailservice-config/mvc-config.xml" })
public class Video1SpringInmemoryUserdetailServiceControllerTest {

The Spring security config file looks as below,

<http pattern="/resources/**" security="none"/>
<http auto-config="true" use-expressions="true" create-session="ifRequired">
<intercept-url pattern="/" access="hasRole('ROLE_ANONYMOUS') or hasRole('ROLE_USER')"/>
<intercept-url pattern="/login/*" access="hasRole('ROLE_ANONYMOUS') or hasRole('ROLE_USER')"/>
<intercept-url pattern="/logout" access="hasRole('ROLE_ANONYMOUS') or hasRole('ROLE_USER')"/>
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/events/" access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>

<form-login login-page="/login/form"
login-processing-url="/login" username-parameter="username" password-parameter="password"
authentication-failure-url="/login/form?error"/>
<logout logout-url="/logout" logout-success-url="/login/form?logout"/>
</http>

<authentication-manager>
<authentication-provider>
<user-service>
<user name="user1@example.com" password="user1" authorities="ROLE_USER"/>
<user name="admin1@example.com" password="admin1" authorities="ROLE_USER,ROLE_ADMIN"/>
</user-service>
</authentication-provider>
</authentication-manager>

In this configuration there are 2 blocks one is http block that describes authentication and authentication-manager that describes authorization. In this example, for authorization we are using org.springframework.security.core.userdetails.memory.InMemoryDaoImpl helper class. To make this example work run the below command,


mvn clean test -Dtest=com.example.springsecurity.web.controllers.Video1SpringInmemoryUserdetailServiceControllerTest

In my next blog I will be introducing Jdbc implementation of authorization.

REFERENCE

Spring Security 3.1 by Robert Winch and Peter Mularien

Debugging Spring Components with Namespace based configuration

Sometimes it hard to debug a Spring component especially if it is Namespace based standard spring components. In this blog I will explain how to debug a spring security component. Consider the below code,

<authentication-manager>
<authentication-provider>
<user-service id="userService">
<user name="${some-user}" password="${some-password}"
authorities="secure-access" />
</user-service>
</authentication-provider>
</authentication-manager>

In the above component if there is a problem with authorization, how do you know what value is being passed? How do you know which class is this and where to put the debug break point? If you notice “user-service” is just another bean with Spring id as “userService”. Namespace based configuration is a syntactic sugar for bean definition. Spring JUnit test and autowiring capability comes to your rescue. Define a simple test function as below,

@Autowired
@Qualifier("userService")
private Object userService;
@Test
public void testUserService(){
assertNotNull(userService);
logger.debug(userService);
}

Run the above test, it will show as green. The logger message will print InMemoryDaoImpl class. Once you know that this is the object you can modify the test as below and further debug,

@Autowired
@Qualifier("userService")
private InMemoryDaoImpl userService;
@Test
public void testUserService(){
assertNotNull(userService);
UserMap map = userService.getUserMap();
//Assuming that krishna is set as dynamic property for some-user
UserDetails user = map.getUser("krishna");
assertNotNull(user);
}

This is one way to debug it, but there might be few other ways. Please suggest me.

I hope this helped.

Container based Security and Spring Security

One of the materials on internet that talks about the differences between Container based Security framework and Spring Security is Spring Security FAQ. It lays down the power of Spring Security. Spring MVC based application and other Spring Based application can take advantage of Spring Security

Authentication is a way to provide user identity so that the application identifies who logged into the system. Authorization is a way to tell who can access which part of the application.

As mentioned in that material Container offers Realm based authentication that resides within a containers server.xml vs as opposed to Spring Security that offers Authentication Providers that sits in the application config file,

A simple Realm is Tomcat’s MemoryRealm and it depends on tomcat-users.xml to configure the users, in reality we use LDAP or any database to store user information.

<!-- in the server.xml -->
<Realm className="org.apache.catalina.realm.MemoryRealm" />

<!-- in the tomcat-users.xml -->
<role rolename="secureconn"/>
<user username="client" password="password" roles="secureconn"/>
<role rolename="secureconn1"/>
<user username="client1" password="password" roles="secureconn1"/>

A simple Authentication Provider looks as below, and it is not specific to a container. Again in reality the user information will be in LDAP or Database.

<authentication-manager>
<authentication-provider>
<!-- <password-encoder ref="encoder"/>-->
<user-service id="accountService">
<user name="client" password="" authorities="secureconn" />
<user name="client1" password="" authorities="secureconn1" />
</user-service>
</authentication-provider>
</authentication-manager>

In container based security the Authorization can be achieved by a simple, security constraint mechanism as below,

<security-constraint>
<web-resource-collection>
<web-resource-name>Demo App</web-resource-name>
<url-pattern>/secure/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>secureconn</role-name>
</auth-constraint>
</security-constraint>

In spring we can achieve Authorization as below, in the spring-security context. The authorization in Container based Security is limited to virtual folder within the container. But with Spring Security we can provide regular expression and secure portions of application.

<http use-expressions="true">
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https"/>
<intercept-url pattern="/secure1/**" access="hasRole('supervisor')"/>
<intercept-url pattern="/secure/**" access="isAuthenticated()" />
</http>

Spring also extends security further to Service layer using a technique called ACL, refer Spring Security document.

If you notice for simple authentication/authorization capabilities container based security is enough, but for more complex enterprise service level security, it make sense to consider Spring Security.

I hope this blog helped.