Spring Security with CAS - SessionTimeout configuration - session-timeout

I have implemented Spring Security with CAS and was trying to configure session timeout. I see that setting values in ticketExpirationPolicies.xml will help with this. I have tried configuring values, but the session never get expired. I have tried setting session expiration in web.xml as well. Here is my spring-application-context configuration:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.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">
<context:property-placeholder />
<http auto-config='true' entry-point-ref="casEntryPoint">
<intercept-url pattern="/**" access="ROLE_ADMIN" />
<custom-filter position="CAS_FILTER" ref="casFilter" />
<logout logout-success-url="/j_spring_cas_security_logout" />
<custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER" />
<custom-filter ref="singleLogoutFilter" before="CAS_FILTER" />
</http>
<beans:bean id="singleLogoutFilter"
class="org.jasig.cas.client.session.SingleSignOutFilter" />
<beans:bean id="requestSingleLogoutFilter"
class="org.springframework.security.web.authentication.logout.LogoutFilter">
<beans:constructor-arg value="https://myipaddress:8443/cas/logout" />
<beans:constructor-arg>
<beans:bean
class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
</beans:constructor-arg>
<beans:property name="filterProcessesUrl" value="/j_spring_cas_security_logout" />
</beans:bean>
<beans:bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="authenticationSuccessHandler">
<beans:bean
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="/" />
</beans:bean>
</beans:property>
</beans:bean>
<beans:bean id="casEntryPoint"
class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<beans:property name="loginUrl"
value="https://myipaddress:8443/cas/login" />
<beans:property name="serviceProperties" ref="serviceProperties" />
</beans:bean>
<beans:bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
<beans:property name="service"
value="https://myipaddress:8443/myApp/j_spring_cas_security_check" />
<beans:property name="sendRenew" value="false" />
</beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="casAuthenticationProvider" />
</authentication-manager>
<beans:bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<beans:property name="userDetailsService" ref="userService" />
<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://myipaddress:8443/cas" />
</beans:bean>
</beans:property>
<beans:property name="key"
value="an_id_for_this_auth_provider_only" />
</beans:bean>
<user-service id="userService">
<user name="user1" password="user1" authorities="ROLE_ADMIN" />
</user-service>
</beans:beans>
I do have Single Signout configuration in web.xml:
<listener>
<listener-class>
org.jasig.cas.client.session.SingleSignOutHttpSessionListener
</listener-class>
</listener>
<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>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

I have found the solution. For each web application which is being authenticated through CAS needs to set their own session-timeout settings in web.xml. Once the session times out for the application, it goes for an authentication at the CAS server. If the ticket has more life, you will be redirected to defaultTargetUrl, if specified. If the ticket is expired, you will be prompted for the credentials again.
How I have configured is that, keeping the ticket expiry to same as the session timeout in my web applications. Once the session times out at my web application, it goes and finds that the ticket is already expired since the validity is same as that of the web application and prompts to login again.

Related

Spring Webflow JSF View Location

i´m trying to setup a JSF application with Spring Web Flow.
I´m using Spring 3.1
Spring faces 2.3.1
JSF (api,impl) 2.1.6
My problem is the following that the program is not taking the correct
location of my jsf views.
I have found some tutorials like
or http://dgparsons.org/jsf-and-spring-webflow.html
for integrating jsf and spring web flow.
In one of these view resolving is done with:
<bean id="faceletsViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.faces.mvc.JsfView"/>
<property name="prefix" value="/WEB-INF/views" />
<property name="suffix" value=".xhtml" />
</bean>
And so I put my xhtml files in the folder /WEB-INF/views/
My Flow is in the directory /WEB-INF/config/flow/start.flow
When I gave it a try the program always wants to open the start.xhtml
from the folder /WEB-INF/config/flow/start.xhtml
So it seems it is completly ignoring the UrlBasedViewResolver.
My FlowBuilderServices is configured as following:
<beans:bean id="flowBuilderServices"
class="org.springframework.webflow.engine.builder.support.FlowBuilderServices">
...
<beans:property name="viewFactoryCreator">
<beans:bean
class="org.springframework.faces.webflow.JsfViewFactoryCreator" />
</beans:property>
...
</beans:bean>
In the tutorials there is no JsfViewFactoryCreator and I cant find a tutorial about it.
As from the javadoc JsfViewFactoryCreator/JsfViewFactory is responsible for the RESTORE_VIEW phase.
So I dived into the source code of the getView() Method of the JsfViewFactory.
JsfViewFactory.java
In line 105
UIViewRoot viewRoot = viewHandler.restoreView(facesContext, viewName);
a FlowViewHandler is called, which generates the wrong path relative to the path of my flow files.
resourcePath = resolveResourcePath(RequestContextHolder.getRequestContext(), viewId);
So my question is now. How can I associate the UrlBasedViewResolver correctly with the flowRegistry/flowbuilderservices so that it takes /WEB-INF/views/*.xthml as my path to the xhtml files.
Or if it is maybe old fashioned to use UrlBasedViewResolver (as I didnt see it in the spring web flow documentation for jsf) how can the webflow beans be configured correctly to use the directories i defined.
For completeness here is my webflow-config.xml file
<!-- Executes flows: the central entry point into the Spring Web Flow system -->
<flow-executor id="flowExecutor">
<flow-execution-listeners>
<listener ref="facesContextListener" />
<listener ref="securityListener" />
</flow-execution-listeners>
</flow-executor>
<!-- The registry of executable flow definitions -->
<flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices"
base-path="/WEB-INF/config/flow">
<flow-location-pattern value="/*.xml" />
</flow-registry>
<beans:bean id="flowBuilderServices"
class="org.springframework.webflow.engine.builder.support.FlowBuilderServices">
<beans:property name="expressionParser">
<beans:bean
class="org.springframework.webflow.expression.el.WebFlowELExpressionParser">
<beans:constructor-arg>
<beans:bean class="com.sun.el.ExpressionFactoryImpl" />
</beans:constructor-arg>
</beans:bean>
</beans:property>
<beans:property name="viewFactoryCreator">
<beans:bean
class="org.springframework.faces.webflow.JsfViewFactoryCreator" />
</beans:property>
<beans:property name="conversionService">
<beans:bean
class="org.springframework.binding.convert.service.DefaultConversionService">
</beans:bean>
</beans:property>
</beans:bean>
So finally I found the way to it myself and it was quite simple.
As written in the documentation of spring webflow under - Specifying view identifiers
Spring Webflow Documentation
the solution is to use an absolute view identifier in the flow definition:
<view-state id="enterBookingDetails" view="/WEB-INF/hotels/booking/bookingDetails.xhtml">
Thus there is no need for a URLBasedViewResolver or a special configuration of JSFViewFactoryCreator.

Trying to get JSF(Faces) working within Spring WebFlow

I been trying to add some JSF(Face) code into my Spring Webflow project but I am getting the following error:
java.lang.IllegalStateException: FacesContext has not been initialized within the current Web Flow request. Check the configuration for your <webflow:flow-executor>. For JSF you will need FlowFacesContextLifecycleListener configured as one of its flow execution listeners.
Here is my flow.xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xmlns:faces="http://www.springframework.org/schema/faces"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd
http://www.springframework.org/schema/faces
http://www.springframework.org/schema/faces/spring-faces-2.2.xsd">
<!-- Executes flows: the central entry point into the Spring Web Flow system -->
<webflow:flow-executor id="flowExecutor">
<webflow:flow-execution-listeners>
<webflow:listener ref="facesContextListener"/>
</webflow:flow-execution-listeners>
</webflow:flow-executor>
<!-- The registry of executable flow definitions -->
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices" base-path="/WEB-INF">
<webflow:flow-location-pattern value="**/*-flow.xml" />
</webflow:flow-registry>
<!-- Configures the Spring Web Flow JSF integration -->
<faces:flow-builder-services id="flowBuilderServices" />
<!-- A listener maintain one FacesContext instance per Web Flow request. -->
<bean id="facesContextListener"
class="org.springframework.faces.webflow.FlowFacesContextLifecycleListener" />
</beans>
and here is my flow:
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<var name="customer" class="org.smith.webflowtemplate.domain.Customer"/>
<view-state id="checkbox-input" model="customer" >
<transition on="submit" to="preview" validate="false"/>
<transition on="cancel" to="thanks" validate="false"/>
</view-state>
<view-state id="preview" model="customer">
<transition on="accept" to="endState"/>
</view-state>
<end-state id="endState" view="/index.jsp" />
</flow>
You need to add a Faces Context listener like this:
<flow-executor id="flowExecutor">
<flow-execution-listeners>
<listener ref="facesContextListener" />
</flow-execution-listeners>
</flow-executor>
<beans:bean id="facesContextListener" class="org.springframework.faces.webflow.FlowFacesContextLifecycleListener" />

spring web security questions

All,
I have my application setup so that i can use a specific username and password combination:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<http use-expressions="true" access-denied-page="/start.jsf">
<intercept-url pattern="/start.jsf" filters="none" />
<intercept-url pattern="/web/**" access="isAuthenticated()" />
<form-login login-page="/start.jsf" default-target-url="/web/user/homepage.jsf" authentication-failure-url="/start.jsf?state=failure"/>
<logout logout-success-url="/start.jsf?state=logout" />
</http>
<!-- <authentication-manager alias="authenticationManager">
<authentication-provider>
<password-encoder hash="md5" />
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="SELECT U.email_address AS username, U.password as password, 'true' as enabled FROM users U where U.email_address=?"
authorities-by-username-query="SELECT U.email_address AS username, 'USER' as authority FROM users U WHERE U.email_address=?"
role-prefix="ROLE_" />
</authentication-provider>
</authentication-manager> -->
<authentication-manager alias="authenticationManager">
<authentication-provider>
<password-encoder hash="md5"/>
<user-service>
<user name="user1" password="a564de63c2d0da68cf47586ee05984d7" authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
Problem is that when I ask it to goto the dataSource, it cannot find the datasource. Reason for this is I have another ApplicationContext.xml in a config folder where all my java source files are. How do people normally organize the project so that this file is able to pickup the datasource file? I want to setup the project accordingly...thanks for the input!
Also, the login works, however, once the user logs in, I want to be able to get the userid/password and I'm not able to. How is that possible?
Implying that you have 2 XML files (in classpath) with spring context config: main-ctx.xml and security-ctx.xml and your are instantiating your app context using main-ctx.xml.
Then you can include config from security-ctx.xml into app context using this in main-ctx.xml (depends on your files locations path may be different):
<import resource="classpath:security-ctx.xml"/>
So you can define dataSource in main-ctx.xml and use it in security-ctx.xml in authentication-manager configuration.

Spring Kerberos Extension, SSO and Machines Outside the Domain

I have been POC'ing with milestone 2 of the Kerberos extension to achieve single sign-on.
Quick summary of my setup:
KDC: Windows Server 2003 (SP2)
Web server: Ubuntu 10.04, Tomcat 5.5, Java 1.6.0_22 (not on the domain)
Spring: Framework 3.0.5, Security 3.0.4, Kerberos Extension 1.0.0 M2
I have setup my configuration to first attempt SPNEGO authentication and if it fails to then redirect to a login page.
This is done by setting SpnegoAuthenticationProcessingFilter's "failureHandler" property. I have successfully tested this
on Windows machines (XP and 7) that are in and out of the domain. The machines that are outside the domain gets redirected to
the login page and then can successfully login.
Here is my config:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<http entry-point-ref="spnegoEntryPoint" auto-config="false">
<intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/j_spring_security_check*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
<custom-filter ref="spnegoAuthenticationProcessingFilter" position="BASIC_AUTH_FILTER" />
<form-login login-page="/login.html" default-target-url="/" always-use-default-target="true"/>
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="kerberosServiceAuthenticationProvider" />
<authentication-provider ref="kerberosAuthenticationProvider"/>
</authentication-manager>
<beans:bean id="spnegoEntryPoint"
class="org.springframework.security.extensions.kerberos.web.SpnegoEntryPoint" />
<beans:bean id="spnegoAuthenticationProcessingFilter"
class="org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter">
<beans:property name="failureHandler">
<beans:bean class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/login.html" />
<beans:property name="allowSessionCreation" value="true"/>
</beans:bean>
</beans:property>
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="kerberosServiceAuthenticationProvider"
class="org.springframework.security.extensions.kerberos.KerberosServiceAuthenticationProvider">
<beans:property name="ticketValidator">
<beans:bean
class="org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator">
<beans:property name="servicePrincipal" value="HTTP/mywebserver.corpza.corp.co.za"/>
<beans:property name="keyTabLocation" value="classpath:mywebserver.keytab" />
<beans:property name="debug" value="true"/>
</beans:bean>
</beans:property>
<beans:property name="userDetailsService" ref="dummyUserDetailsService" />
</beans:bean>
<beans:bean id="kerberosAuthenticationProvider" class="org.springframework.security.extensions.kerberos.KerberosAuthenticationProvider">
<beans:property name="kerberosClient">
<beans:bean class="org.springframework.security.extensions.kerberos.SunJaasKerberosClient">
<beans:property name="debug" value="true" />
</beans:bean>
</beans:property>
<beans:property name="userDetailsService" ref="dummyUserDetailsService" />
</beans:bean>
<beans:bean class="org.springframework.security.extensions.kerberos.GlobalSunJaasKerberosConfig">
<beans:property name="debug" value="true" />
<beans:property name="krbConfLocation" value="/etc/krb5.conf" />
</beans:bean>
<beans:bean id="dummyUserDetailsService" class="main.server.DummyUserDetailsService"/>
</beans:beans>
When the Windows machine is outside the domain my web server responds with the "WWW-Authenticate Negotiate" header (as per usual) to which
the Windows machine responds to with a NTLM header ("Negotiate TlRM..."), where the SpnegoAuthenticationProcessingFilter then says "Negotiate Header was invalid..."
and awesomly redirects the user to the login page. Great.
The Issue:
There are a number of Mac and Linux machines that are permanently outside the domain which would need to use this web app.
When they hit the web app (with Firefox 3.6) my web server responds with the expected "WWW-Authenticate Negotiate" header to inform
the client that the web app is Kerberized, BUT neither the Mac or Linux machines responds at all. Thus the SpnegoAuthenticationProcessingFilter
doesn't get entered again and hence no failure and subsequently no redirection to the login page takes place.
The Question:
Why doesn't the Mac and Linux machines respond in the same way as the Windows machines (can't belive I just asked that...)?
I know that when the Mac and Linux machines obtain a ticket (via kinit) they are able to authenticated but this doesn't seem like a good solution
at all as it requires effort from the user to provide credentials etc. where the tickets expires as well.
So is there any way that we can get these machines to send back a NTLM header as the Windows machines does?
Or if there are any other suggestions/ways please let me know.
B.t.w. I did configure the Firefoxes that I used on to test on the Mac and Linux machines ("network.negotiate-auth.delegation-uris" and "network.negotiate-auth.trusted-uris" was set to ".corpza.corp.co.za").
It doesn't look like you set network.automatic-ntlm-auth.trusted-uris. Did you read through this?
https://developer.mozilla.org/en/Integrated_Authentication
Grant
You are going the wrong way. Don't rely on the failing SPNEGO filter. The Linux and Mac clients behave correctly just as the Windows client does. The general setup should look like the following, if the filter does not implement/support that, you have found a bug.
Client sends a request to the server
Client receives "401 WWW-Authenticate: Negotiate" from the server (or any combination of Negotiate, Basic, Digest).
Client tries to supply auth data and if it fails it shows the 401 page.
Now you rely on faulty/non-processible data sent from the Windows client to present the form. You should rather send the form with the 401 directly to give all clients the ability to choose an appropriate login method (SPNEGO or form, ie. fail-through). Keep in mind that form auth is not an http auth like Negotiate, Digest or Basic. It has to be treated differently.
We are using that filter too and I am not really happy with it. So I have hands-on experience.

Require authentication through https with spring security?

I'm using tomcat 6, spring mvc 3.0.0 and spring security 3.0.0, and since the passwords I store in the database are sha1 hashed, I can't use digest authentication (section 9.2.1 of the documentation spells that out). For this reason, I need to make authentication happen through https.
Due to potential processing overhead, I want to keep as much of the traffic in regular http as possible. Is there a way I can make spring use https for unathenticated requests, then use http once authentication is done? I think this is done with a ChannelProcessingFilter of some sort, but I'm stumped as to the particulars.
Here's my application-security.xml file as it currently stands:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<http use-expressions="true">
<intercept-url pattern="/**" access="isAuthenticated()" />
<http-basic />
</http>
<authentication-manager>
<authentication-provider user-service-ref="myUserDetailsService">
<password-encoder hash="sha"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="myUserDetailsService"
class="path.to.myUserDetailsServiceImpl">
</beans:bean>
</beans:beans>
Thanks for the help.
If at any point you pass a session id over HTTP you are violating OWASP A9. An attacker doesn't need the password if he has the session id. I would not implement this feature in your application, https is very light weight and I think you should look into saving resources in places that doesn't mean that your clients will be hacked.
Not sure exactly how to do it using Spring MVC but I did accomplish this using Grails with Spring Security 3...if you are interested you can see my blog post here.
Because that will not really help you...I did a quick google search and found this post which looks correct and says to configure your web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext-security.xml
</param-value>
</context-param>
<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>
and your applicationContext-security.xml as such:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">
<http>
<intercept-url pattern="/url1.htm"
access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https" />
<intercept-url pattern="/url2.htm"
access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https" />
<intercept-url pattern="/**"
access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="http" />
<anonymous />
<http-basic/>
</http>
<!-- This bean is optional; it isn't used by any other bean as it only listens and logs -->
<beans:bean id="loggerListener" class="org.springframework.security.event.authentication.LoggerListener"/>
</beans:beans>
Also take a look at this site for more info and how to configure tomcats SSL connector.

Resources