I am a newbie to Spring Security and CAS. I got the SSO part working but am struggling with getting the authorization part working. I followed this to implement custom authorisation
http://www.theserverside.com/tip/-Spring-Security-Customizing-Your-User-and-Authorization-in
When should the loadUserDetails get called. I have set a break point here and this method is never called.
Any help will be greatly appreciated. Looks like I am missing a configuration to invoke the authorization.
I want to have my custom User object populated with the authorities and reside in session so that I can check User role at any stage.
When I log in the logs here is steps that happen once I login
1. /indexCasePackOptions?ticket=ST-4295-4eFUHVziBcmVaOd3bifl-cas at position 1 of 8 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' (FilterChainProxy:329)
No HttpSession currently exists (HttpSessionSecurityContextRepository:127)
No SecurityContext was available from the HttpSession: null. A new one will be created. (HttpSessionSecurityContextRepository:85)
2. /indexCasePackOptions?ticket=ST-4295-4eFUHVziBcmVaOd3bifl-cas at position 2 of 8 in additional filter chain; firing Filter: 'CasAuthenticationFilter' (FilterChainProxy:329)
3. /indexCasePackOptions?ticket=ST-4295-4eFUHVziBcmVaOd3bifl-cas at position 3 of 8 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' (FilterChainProxy:329)
4. /indexCasePackOptions?ticket=ST-4295-4eFUHVziBcmVaOd3bifl-cas at position 4 of 8 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' (FilterChainProxy:329)
5. /indexCasePackOptions?ticket=ST-4295-4eFUHVziBcmVaOd3bifl-cas at position 5 of 8 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' (FilterChainProxy:329)
Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@6faa93c2: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffffe21a: RemoteIpAddress: 192.168.0.124; SessionId: null; Granted Authorities: ROLE_ANONYMOUS' (AnonymousAuthenticationFilter:102)
6. /indexCasePackOptions?ticket=ST-4295-4eFUHVziBcmVaOd3bifl-cas at position 6 of 8 in additional filter chain; firing Filter: 'SessionManagementFilter' (FilterChainProxy:329)
7. /indexCasePackOptions?ticket=ST-4295-4eFUHVziBcmVaOd3bifl-cas at position 7 of 8 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' (FilterChainProxy:329)
8. /indexCasePackOptions?ticket=ST-4295-4eFUHVziBcmVaOd3bifl-cas at position 8 of 8 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' (FilterChainProxy:329)
Checking match of request : '/indexcasepackoptions'; against '/login/**' (AntPathRequestMatcher:103)
Secure object: FilterInvocation: URL: /indexCasePackOptions?ticket=ST-4295-4eFUHVziBcmVaOd3bifl-cas; Attributes: [ROLE_ANONYMOUS] (FilterSecurityInterceptor:193)
Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@6faa93c2: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffffe21a: RemoteIpAddress:
192.168.0.124; SessionId: null; Granted Authorities: ROLE_ANONYMOUS (FilterSecurityInterceptor:298)
Voter: org.springframework.security.access.vote.RoleVoter@7077602d, returned: 1 (AffirmativeBased:65)
Authorization successful (FilterSecurityInterceptor:214)
RunAsManager did not change Authentication object (FilterSecurityInterceptor:226)
/indexCasePackOptions?ticket=ST-4295-4eFUHVziBcmVaOd3bifl-cas reached end of additional filter chain; proceeding with original chain (FilterChainProxy:315)
No Proxy Ticket found for (ProxyGrantingTicketStorageImpl:77)
SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession. (HttpSessionSecurityContextRepository:269)
Chain processed normally (ExceptionTranslationFilter:115)
SecurityContextHolder now cleared, as request processing completed (SecurityContextPersistenceFilter:97)
My custom UserDetails
package com.creata.domain;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
public class User implements Serializable, UserDetails {
private static final long serialVersionUID = 1L;
private Collection<SimpleGrantedAuthority> authorities;
private final String username;
private String password;
public User(String username) {
this.username=username;
}
@Override
public Collection<SimpleGrantedAuthority> getAuthorities() {
return authorities;
}
public void setUserAuthorities(List<String> roles) {
List<SimpleGrantedAuthority> listOfAuthorities = new ArrayList<SimpleGrantedAuthority>();
for (String role : roles) {
listOfAuthorities.add(new SimpleGrantedAuthority(role));
}
authorities = listOfAuthorities;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return true;
}
}
My custom UserService
package com.creata.security.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import com.creata.domain.User;
public class CustomUserService implements UserDetailsService, AuthenticationUserDetailsService {
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
System.out.println("loadUserByUsername called here ");
User currentUser = new User("Reena");
//Collection<SimpleGrantedAuthority> authorities = currentUser.getAuthorities();
List<String> roles = new ArrayList<String>();
roles.add("ROLE_Admin");
roles.add("ROLE_CPAD-Maintenance");
currentUser.setUserAuthorities(roles);
//authorities.add(new SimpleGrantedAuthority("PRIVILEGE_HOME"));
return currentUser;
}
@Override
public UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException{
User currentUser = new User("Reena");
List<String> roles = new ArrayList<String>();
roles.add("ROLE_Admin");
roles.add("ROLE_CPAD-Maintenance");
currentUser.setUserAuthorities(roles);
//authorities.add(new SimpleGrantedAuthority("PRIVILEGE_HOME"));
return currentUser;
}
}
Here is my security configuration:
<beans:beans
xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<http entry-point-ref="casEntryPoint">
<custom-filter position="CAS_FILTER" ref="casFilter" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="casAuthenticationProvider" />
</authentication-manager>
<beans:bean id="casFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager"/>
</beans:bean>
<beans:bean id="casEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<beans:property name="loginUrl" value="https://abc.com/cas/login"/>
<beans:property name="serviceProperties" ref="serviceProperties"/>
</beans:bean>
<beans:bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<beans:property name="authenticationUserDetailsService" ref="customUserService"/>
<beans:property name="serviceProperties" ref="serviceProperties" />
<beans:property name="ticketValidator">
<beans:bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<beans:constructor-arg index="0" value="https://portal.creata.com/cas" />
</beans:bean>
</beans:property>
<beans:property name="key" value="an_id_for_this_auth_provider_only"/>
</beans:bean>
<beans:bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
<beans:property name="service" value="https://mypc.abc.com/Spring_CPAD2/"/>
</beans:bean>
<beans:bean id="customUserService" class="com.creata.security.service.CustomUserService"/>
</beans:beans>
Here is my web.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
metadata-complete="true">
<display-name />
<context-param>
<param-name>serverName</param-name>
<param-value>https://cpaus-rsingh2.creata.com</param-value>
</context-param>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter>
<filter-name>CAS Authentication Filter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>https://abc.com/cas/login?AppName=app1</param-value>
</init-param>
</filter>
<filter>
<filter-name>CAS Validation Filter</filter-name>
<filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>https://abc.com/cas</param-value>
</init-param>
</filter>
<filter>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS Authentication Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<filter>
<filter-name>ResponseOverrideFilter</filter-name>
<filter-class>org.displaytag.filter.ResponseOverrideFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ResponseOverrideFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter>
<description>generated-persistence-filter</description>
<filter-name>com_ibm_db2_jcc_DB2DriverFilter</filter-name>
<filter-class>
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
</filter-class>
<init-param>
<param-name>entityManagerFactoryBeanName</param-name>
<param-value>com_ibm_db2_jcc_DB2Driver</param-value>
</init-param>
</filter>
<filter>
<description>generated-sitemesh-filter</description>
<filter-name>Sitemesh Filter</filter-name>
<filter-class>
com.opensymphony.module.sitemesh.filter.PageFilter
</filter-class>
</filter>
<!-- <filter>
<description>generated-persistence-filter</description>
<filter-name>MyEclipse_DerbyFilter</filter-name>
<filter-class>
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
</filter-class>
<init-param>
<param-name>entityManagerFactoryBeanName</param-name>
<param-value>MyEclipse_Derby</param-value>
</init-param>
</filter> -->
<filter-mapping>
<filter-name>com_ibm_db2_jcc_DB2DriverFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Sitemesh Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- <filter-mapping>
<filter-name>MyEclipse_DerbyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> -->
<servlet>
<description>generated-servlet</description>
<servlet-name>Spring_CPAD2 Servlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:Spring_CPAD2-web-context.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<description>generated-resources-servlet</description>
<servlet-name>Resource Servlet</servlet-name>
<servlet-class>
org.springframework.js.resource.ResourceServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<description>generated-webflow-servlet</description>
<servlet-name>webflow</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/Spring_CPAD2-webflow-config.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Resource Servlet</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Spring_CPAD2 Servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>webflow</servlet-name>
<url-pattern>*.flow</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>jsp/intro.jsp</welcome-file>
</welcome-file-list>
<jsp-config>
<taglib>
<taglib-uri>MyCustomTags</taglib-uri>
<taglib-location>/WEB-INF/tlds/MyCustomTags.tld</taglib-location>
</taglib>
</jsp-config>