Adding Remember Me functionality in already configured spring OUTH and usernamepassword token authentication system - spring

I have the following spring security configuration.
<?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:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!-- For S2OAuth endpoints -->
<http pattern="/oauth/token"
create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
entry-point-ref="oauthAuthenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="oauthAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
</http>
<http use-expressions="true">
<!-- Authentication policy -->
<form-login login-page="/signin" login-processing-url="/signin/authenticate" authentication-failure-url="/signin?error=1" />
<logout logout-url="/signout" delete-cookies="JSESSIONID" />
<!-- Remember Me -->
<remember-me services-ref="rememberMeServices" key="myRememberMeKey" />
<!-- Authorization policy definition: TODO consider replacing with #Secured on #Controllers -->
<intercept-url pattern="/" access="permitAll" />
<intercept-url pattern="/favicon.ico" access="permitAll" />
<intercept-url pattern="/members/**" access="permitAll" />
<intercept-url pattern="/groups/**" access="permitAll" />
<intercept-url pattern="/pubsub/**" access="permitAll" />
<intercept-url pattern="/resources/**" access="permitAll" />
<intercept-url pattern="/signup" access="permitAll" requires-channel="#{environment['application.secureChannel']}" />
<intercept-url pattern="/signin" access="permitAll" requires-channel="#{environment['application.secureChannel']}" />
<intercept-url pattern="/signin/*" access="permitAll" requires-channel="#{environment['application.secureChannel']}" />
<intercept-url pattern="/reset" access="permitAll" requires-channel="#{environment['application.secureChannel']}" />
<!-- TODO this would probably be better mapped to simply /invite?token={token} but not able to vary security policy here based on presence of a request parameter. Consider #Secured on #Controller. -->
<intercept-url pattern="/invite/accept" access="permitAll" requires-channel="#{environment['application.secureChannel']}" />
<!-- TODO this should be restricted to admin users only -->
<intercept-url pattern="/admin/**" access="permitAll" />
<intercept-url pattern="/**" access="isAuthenticated()" requires-channel="#{environment['application.secureChannel']}" />
<custom-filter ref="resourceServerFilter" before="EXCEPTION_TRANSLATION_FILTER" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="usernamePasswordAuthenticationProvider" />
</authentication-manager>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" xmlns="http://www.springframework.org/schema/beans">
<constructor-arg>
<list>
<bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
<bean class="org.springframework.security.access.vote.RoleVoter" />
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</list>
</constructor-arg>
</bean>
<bean id="jdbcRememberMeRepository" class="com.springsource.greenhouse.rememberme.JdbcRememberMeRepository" xmlns="http://www.springframework.org/schema/beans"/>
<bean id="coreUserDetailsService" class="com.springsource.greenhouse.rememberme.RememberMeUserDetailsService" xmlns="http://www.springframework.org/schema/beans"/>
<bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices" xmlns="http://www.springframework.org/schema/beans">
<property name="tokenRepository" ref="jdbcRememberMeRepository" />
<property name="userDetailsService" ref="coreUserDetailsService" />
<property name="key" value="myRememberMeKey" />
<property name="alwaysRemember" value="true" />
</bean>
<!-- For S2OAuth endpoints -->
<authentication-manager id="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<beans:bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<beans:constructor-arg ref="clientDetails" />
</beans:bean>
<beans:bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="realmName" value="greenhouseApi" />
</beans:bean>
<beans:import resource="security-oauth-provider.xml" />
</beans:beans>
When I tick the remember-me checkbox , I see my remember-me database is populated as shown in the snapshot. Now I close the browser and try to access the url which needs sign-in. I am able to see the page. Now here I am confused about whether I am able to see the page because of login or because of remember-me. Secondly I see in the remember-me database table the last date is not updated. What can be the reasons for this?

Restarting your browser is not enough. To test remember me functionality you need to be sure that your session is expired. If lastUsed was not updated then it means that remember me functionality was not used. In your case HTTP session was active. You need to deactivate it and there are multiple options to do it:
wait for session expiration. Hint: you can set minimal session timeout, for example set 1 minute in your web.xml.
or remove session cockie (do not remove all coockies for your domain, remember me use coockie too)
or stop your application server then clean up a directory where it persist session data and start it again. For tomcat it is tomcat_root/work.
Setting up session timeout value to 1 minute in web.xml:
<session-config>
<session-timeout>1</session-timeout>
</session-config>

Related

Redirect all tabs to login page after logout in one tab with Spring Security

Currently, I am having a problem with Spring Security as when I open two tabs and I logout in one tab, the session is sure to be destroyed but I can still make some action on the other tab, which is supposed to redirect me to login page instead of letting me make any other action so far.
Not until I refresh the page, it will redirect to the login page as no valid session any more.
I am trying to find a solution to force the other tabs to redirect to logout page without letting the user doing any thing else as they logout in the other tab.
I wonder if we could achieve such a thing with Spring Security configuration?
Below is my spring-security.xml
<!-- Secure token end point -->
<http pattern="/api/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<custom-filter ref="clientCredentialsTokenEndpointFilter"
before="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<!-- secure api service -->
<http pattern="/api/service/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint" xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/api/service/**" method="GET"
access="IS_AUTHENTICATED_FULLY" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http auto-config="true" use-expressions="true"
xmlns="http://www.springframework.org/schema/security"
authentication-manager-ref="userAuthenticationManager">
<access-denied-handler error-page="/accessDenied" />
<intercept-url pattern="/home/**" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')" />
<intercept-url pattern="/index" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')" />
<intercept-url pattern="/pages/**" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/overviewOfferLetter" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_MANAGER') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/importOldCandidate" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/RecruitmentEvent" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/questionnaireResultId**" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_INTERVIEWER')"/>
<intercept-url pattern="/evaluation**" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_INTERVIEWER')"/>
<intercept-url pattern="/questionnaireResult" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_CV_SCREENER') or hasRole('ROLE_MANAGER')"/>
<intercept-url pattern="/activityLogs" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/oldCandidate" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/advancedSearch" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/listApplicants" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/duplicatedEmail" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/createApplicant" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')"/>
<intercept-url pattern="/jobHistory" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')" />
<intercept-url pattern="/importOldCandidate" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')" />
<intercept-url pattern="/oldCandidate" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')" />
<intercept-url pattern="/importApplicant" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_HR')" />
<form-login login-page="/login"
default-target-url="/index"
always-use-default-target="true"
authentication-failure-url="/login?error=incorrect"
authentication-success-handler-ref="customAuthenticationSuccessHandler"
username-parameter="username"
password-parameter="password"
/>
<logout logout-success-url="/login?logout" delete-cookies="JSESSIONID" />
</http>
<bean id="customAuthenticationSuccessHandler" class="com.axonactive.security.CustomAuthenticationSuccessHandler" />
<authentication-manager id="userAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider ref="authenticationProvider">
</authentication-provider>
</authentication-manager>
<bean id="authenticationProvider" class="com.axonactive.security.CustomAuthenticationProvider"></bean>
<global-method-security secured-annotations="enabled"
pre-post-annotations="enabled" proxy-target-class="true"
xmlns="http://www.springframework.org/schema/security">
<expression-handler ref="expressionHandler" />
</global-method-security>
<bean id="expressionHandler"
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator">
<bean id="permissionEvaluator" class="com.axonactive.security.AccountPermissionEvaluator" />
</property>
</bean>
<bean id="webExpressionHandler"
class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
<property name="permissionEvaluator">
<bean id="permissionEvaluator" class="com.axonactive.security.AccountPermissionEvaluator" />
</property>
</bean>
<!-- Define LDAP Service -->
<bean id="ldapService" class="com.axonactive.service.implement.LdapService">
<property name="contextFactory" value="${ldap.contextFactory}" />
<property name="url" value="${ldap.url}" />
<property name="securityAuthentication" value="${ldap.securityAuthentication}" />
<property name="username" value="${ldap.username}" />
<property name="password" value="${ldap.password}" />
<property name="searchBase" value="${ldap.searchBase}" />
<property name="searchName" value="${ldap.searchName}" />
<property name="distinguishedName" value="${ldap.distinguishedName}" />
</bean>
<!-- End LDAP Service -->
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="springsec/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
</bean>
<!-- End point filter for client -->
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
<!-- Client credential authentication manager -->
<authentication-manager alias="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<!-- Declare client service -->
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetailsService" />
</bean>
<!-- Declare client list -->
<oauth:client-details-service id="clientDetailsService">
<oauth:client client-id="testSystem"
secret="9346336818f9d382a22ac5d4486fa5ee" scope="read"
authorized-grant-types="client_credentials" />
</oauth:client-details-service>
<!-- Config oauth server -->
<oauth:authorization-server
client-details-service-ref="clientDetailsService" token-services-ref="tokenServices">
<oauth:client-credentials />
</oauth:authorization-server>
<!-- Declare resource server, where the token token are store -->
<oauth:resource-server id="resourceServerFilter"
resource-id="springsec" token-services-ref="tokenServices" />
<!-- Store token in memory -->
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
<constructor-arg ref="dataSource" />
</bean>
<!-- Configuration token service , expire in one day, don't support refresh
token -->
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="false" />
<property name="accessTokenValiditySeconds" value="86400"></property>
<property name="clientDetailsService" ref="clientDetailsService" />
</bean>
If there is any other files or information you guys need to see, please tell me.
As #kryger said, your client-side code would need to check if your session is still authenticated. We have a similar problem with our client app, in that Spring wants to redirect unauthorized request, but our client app is communicating with our server in a "rest-ful" way, so the client app just fails silently to the end user.
We solve this issue by having a second AuthenticationEntryPoint, specifically with Http403ForbiddenEntryPoint. By using the Http403ForbiddenEntryPoint.html, all unauthorized request by our client app get a HTTP 403 error vs a traditional Spring security redirect. Then our client app is configured with an interceptor to listen for any 403 errors and prompt the user with a signin.
Here's an example Spring Security configuration using Http403ForbiddenEntryPoint from our WebSecurityConfigurerAdapter config.
/**
* Configures all the AuthenticationEntryPoints for our app
*/
protected DelegatingAuthenticationEntryPoint delegatingAuthenticationEntryPoint() {
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints =
new LinkedHashMap<RequestMatcher, AuthenticationEntryPoint>();
// entry point for unauthenticated client apps
entryPoints.put(new SecuredApiRequestMatcher(), new Http403ForbiddenEntryPoint());
// entry point for our normal website
DelegatingAuthenticationEntryPoint delegatingEntryPoint =
new DelegatingAuthenticationEntryPoint(entryPoints);
delegatingEntryPoint.setDefaultEntryPoint(new LoginUrlAuthenticationEntryPoint(SIGNIN_URL));
return delegatingEntryPoint;
}
/**
* {#link RequestMatcher} that checks if requested url matches a secured api path.
*/
final class SecuredApiRequestMatcher implements RequestMatcher {
final Map<String, String[]> securedMethodToUrlMap;
public SecuredApiRequestMatcher() {
securedMethodToUrlMap = new HashMap<String, String[]>();
securedMethodToUrlMap.put(GET.name(), SECURED_GET_URLS);
securedMethodToUrlMap.put(PUT.name(), SECURED_PUT_URLS);
securedMethodToUrlMap.put(POST.name(), SECURED_POST_URLS);
securedMethodToUrlMap.put(DELETE.name(), SECURED_DELETE_URLS);
}
#Override
public boolean matches(HttpServletRequest request) {
String url = UrlUtils.buildRequestUrl(request);
String method = request.getMethod();
String[] securedUrls = securedMethodToUrlMap.get(method);
if(securedUrls != null) {
for(String securedUrl : securedUrls) {
if(url.startsWith(securedUrl))
return true;
}
}
return false;
}
}
Finally, here's the response from the Http403ForbiddenEntryPoint
{"timestamp":1430938979916,"status":403,"error":"Forbidden","message":"Access
Denied","path":"/api/secured/url"}

Adding Remember Me functionality throws exception

I have the following spring security configuration.
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!-- For S2OAuth endpoints -->
<http pattern="/oauth/token"
create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
entry-point-ref="oauthAuthenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="oauthAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
</http>
<http use-expressions="true">
<!-- Authentication policy -->
<form-login login-page="/signin" login-processing-url="/signin/authenticate" authentication-failure-url="/signin?error=1" />
<logout logout-url="/signout" delete-cookies="JSESSIONID" />
<!-- Authorization policy definition: TODO consider replacing with #Secured on #Controllers -->
<intercept-url pattern="/" access="permitAll" />
<intercept-url pattern="/favicon.ico" access="permitAll" />
<intercept-url pattern="/members/**" access="permitAll" />
<intercept-url pattern="/groups/**" access="permitAll" />
<intercept-url pattern="/pubsub/**" access="permitAll" />
<intercept-url pattern="/resources/**" access="permitAll" />
<intercept-url pattern="/signup" access="permitAll" requires-channel="#{environment['application.secureChannel']}" />
<intercept-url pattern="/signin" access="permitAll" requires-channel="#{environment['application.secureChannel']}" />
<intercept-url pattern="/signin/*" access="permitAll" requires-channel="#{environment['application.secureChannel']}" />
<intercept-url pattern="/reset" access="permitAll" requires-channel="#{environment['application.secureChannel']}" />
<!-- TODO this would probably be better mapped to simply /invite?token={token} but not able to vary security policy here based on presence of a request parameter. Consider #Secured on #Controller. -->
<intercept-url pattern="/invite/accept" access="permitAll" requires-channel="#{environment['application.secureChannel']}" />
<!-- TODO this should be restricted to admin users only -->
<intercept-url pattern="/admin/**" access="permitAll" />
<intercept-url pattern="/**" access="isAuthenticated()" requires-channel="#{environment['application.secureChannel']}" />
<custom-filter ref="resourceServerFilter" before="EXCEPTION_TRANSLATION_FILTER" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="usernamePasswordAuthenticationProvider" />
</authentication-manager>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" xmlns="http://www.springframework.org/schema/beans">
<constructor-arg>
<list>
<bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
<bean class="org.springframework.security.access.vote.RoleVoter" />
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</list>
</constructor-arg>
</bean>
<!-- Remember Me -->
<http>
<remember-me services-ref="rememberMeServices" key="myRememberMeKey" />
</http>
<bean id="jdbcRememberMeRepository" class="com.springsource.greenhouse.rememberme.JdbcRememberMeRepository" xmlns="http://www.springframework.org/schema/beans"/>
<bean id="coreUserDetailsService" class="com.springsource.greenhouse.rememberme.CoreUserDetailsService" xmlns="http://www.springframework.org/schema/beans"/>
<bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices" xmlns="http://www.springframework.org/schema/beans">
<property name="tokenRepository" ref="jdbcRememberMeRepository" />
<property name="userDetailsService" ref="coreUserDetailsService" />
<property name="key" value="myRememberMeKey" />
<property name="alwaysRemember" value="true" />
</bean>
<!-- For S2OAuth endpoints -->
<authentication-manager id="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<beans:bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<beans:constructor-arg ref="clientDetails" />
</beans:bean>
<beans:bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="realmName" value="greenhouseApi" />
</beans:bean>
<beans:import resource="security-oauth-provider.xml" />
</beans:beans>
I am getting the following exception.
Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: No AuthenticationEntryPoint could be established. Please make sure you have a login mechanism configured through the namespace (such as form-login) or specify a custom AuthenticationEntryPoint with the 'entry-point-ref' attribute
Offending resource: class path resource [com/springsource/greenhouse/config/security.xml]
at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68)
...
I am new to spring security. I don't know the cause of this exception.
You cannot add your remember-me declaration into new empty http element. Use some other existed http element where authentication entry point is already configured (for example via form-login element):
<http use-expressions="true">
<!-- Authentication policy -->
<form-login login-page="/signin" login-processing-url="/signin/authenticate" authentication-failure-url="/signin?error=1" />
<remember-me services-ref="rememberMeServices" key="myRememberMeKey" />
...
<http/>

Spring security switching to http after login. How can I keep it as https?

I am using Spring MVC and Spring Security. My redirects were switching https to http until I found this post. Spring MVC "redirect:" prefix always redirects to http -- how do I make it stay on https?. I also had to set the redirectHttp10Compatible property to false in my AjaxUrlBasedViewResolver.
The problem is that https still switches to http after login. Once I am logged in I can set my app back to https in the address bar and it will stick. Also, I am using IP authentication for most users in which case https stays thanks to the solution above.
I am trying to add redirectHtp10Compatible to login_security_check or something like that but am stuck. Here my security-config.xml.
<?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:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.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">
<global-method-security pre-post-annotations="enabled" />
<http auto-config='true' access-denied-page="/login">
<intercept-url pattern="/static/styles/**" filters="none" />
<intercept-url pattern="/static/scripts/**" filters="none" />
<intercept-url pattern="/login/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/error/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/api/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/ajaxTimeOut" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/checkSystem" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/adminUser/**" access="ROLE_SSADMIN" />
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login login-page="/ajaxTimeOut" login-processing-url="/login_security_check" authentication-failure-url="/login?login_error=t" default-target-url="/" always-use-default-target="true" />
<logout logout-url="/logout" logout-success-url="/"/>
<custom-filter position="PRE_AUTH_FILTER" ref="ipPreAuthFilter" />
</http>
<beans:bean id="ipAuthDetailsSource" class="com.mydomain.security.IPBasedPreAuthenticatedDetailsSource" />
<beans:bean id="ipPreAuthFilter" class="com.mydomain.security.IPPreAuthenticationFilter">
<beans:property name="authenticationManager" ref="preAuthManager" />
<beans:property name="authenticationDetailsSource" ref="ipAuthDetailsSource" />
</beans:bean>
<beans:bean id="preAuthManager" class="org.springframework.security.authentication.ProviderManager">
<beans:property name="providers">
<beans:list>
<beans:ref local="preAuthProvider"/>
</beans:list>
</beans:property>
</beans:bean>
<beans:bean id="preAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService" ref="preAuthUserService" />
</beans:bean>
<beans:bean id="preAuthUserService" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService" />
<authentication-manager>
<authentication-provider user-service-ref="userService">
<password-encoder ref="passwordEncoder" >
<salt-source user-property="salt" />
</password-encoder>
</authentication-provider>
</authentication-manager>
<beans:bean id="userService" class="com.mydomain.security.UserServiceImpl" />
<beans:bean id="passwordEncoder" class="com.mydomain.security.PasswordEncoder">
<beans:constructor-arg value="256" />
</beans:bean>
Have you tried this:
<http>
<intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/>
...
</http>
http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-requires-channel
Got the solution.
<security:form-login login-page="/Login"
login-processing-url="/j_spring_security_check"
default-target-url="https://127.0.0.1/abcWeb/"
always-use-default-target="true"
authentication-failure-url="https://127.0.0.1/abcWeb/loginfailed"
/>
<security:logout logout-success-url="https://127.0.0.1/abcWeb/logout" />
I have added absolute path for login processing and for the rest I had added this p:redirectHttp10Compatible="false" to InternalViewResolver

Spring security switching to http after login. How can I keep https?

I am using Spring MVC and Spring Security. My redirects were switching https to http until I found this post. Spring MVC "redirect:" prefix always redirects to http -- how do I make it stay on https?. I also had to set the redirectHttp10Compatible property to false in my AjaxUrlBasedViewResolver.
The problem is that https still switches to http after login. Once I am logged in I can set my app back to https in the address bar and it will stick. Also, I am using IP authentication for most users in which case https stays thanks to the solution above.
I am trying to add redirectHtp10Compatible to login_security_check or something like that but am stuck. Here my security-config.xml.
<?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:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.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">
<global-method-security pre-post-annotations="enabled" />
<http auto-config='true' access-denied-page="/login">
<intercept-url pattern="/static/styles/**" filters="none" />
<intercept-url pattern="/static/scripts/**" filters="none" />
<intercept-url pattern="/login/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/error/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/api/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/ajaxTimeOut" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/checkSystem" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/adminUser/**" access="ROLE_SSADMIN" />
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login login-page="/ajaxTimeOut" login-processing-url="/login_security_check" authentication-failure-url="/login?login_error=t" default-target-url="/" always-use-default-target="true" />
<logout logout-url="/logout" logout-success-url="/"/>
<custom-filter position="PRE_AUTH_FILTER" ref="ipPreAuthFilter" />
</http>
<beans:bean id="ipAuthDetailsSource" class="com.mydomain.security.IPBasedPreAuthenticatedDetailsSource" />
<beans:bean id="ipPreAuthFilter" class="com.mydomain.security.IPPreAuthenticationFilter">
<beans:property name="authenticationManager" ref="preAuthManager" />
<beans:property name="authenticationDetailsSource" ref="ipAuthDetailsSource" />
</beans:bean>
<beans:bean id="preAuthManager" class="org.springframework.security.authentication.ProviderManager">
<beans:property name="providers">
<beans:list>
<beans:ref local="preAuthProvider"/>
</beans:list>
</beans:property>
</beans:bean>
<beans:bean id="preAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService" ref="preAuthUserService" />
</beans:bean>
<beans:bean id="preAuthUserService" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService" />
<authentication-manager>
<authentication-provider user-service-ref="userService">
<password-encoder ref="passwordEncoder" >
<salt-source user-property="salt" />
</password-encoder>
</authentication-provider>
</authentication-manager>
<beans:bean id="userService" class="com.mydomain.security.UserServiceImpl" />
<beans:bean id="passwordEncoder" class="com.mydomain.security.PasswordEncoder">
<beans:constructor-arg value="256" />
</beans:bean>
Thanks.
Add the requires-channel attribute to your secure urls in the intercep-url nodes
just like this:
<intercept-url pattern="/**" access="ROLE_USER" requires-channel="https" />

Infinite loop using Spring Security - Login page is protected even though it should allow anonymous access

I have a Spring application (Spring version 2.5.6.SEC01, Spring Security version 2.0.5) with the following setup:
web.xml
<welcome-file-list>
<welcome-file>
index.jsp
</welcome-file>
</welcome-file-list>
The index.jsp page is in the WebContent directory and simply contains a redirect:
<c:redirect url="/login.htm"/>
In the appname-servlet.xml, there is a view resolver to point to the jsp pages in WEB-INF/jsp
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
In the security-config.xml file, I have the following configuration:
<http>
<!-- Restrict URLs based on role -->
<intercept-url pattern="/WEB-INF/jsp/login.jsp*" access="ROLE_ANONYMOUS" />
<intercept-url pattern="/WEB-INF/jsp/header.jsp*" access="ROLE_ANONYMOUS" />
<intercept-url pattern="/WEB-INF/jsp/footer.jsp*" access="ROLE_ANONYMOUS" />
<intercept-url pattern="/login*" access="ROLE_ANONYMOUS" />
<intercept-url pattern="/index.jsp" access="ROLE_ANONYMOUS" />
<intercept-url pattern="/logoutSuccess*" access="ROLE_ANONYMOUS" />
<intercept-url pattern="/css/**" filters="none" />
<intercept-url pattern="/images/**" filters="none" />
<intercept-url pattern="/**" access="ROLE_ANONYMOUS" />
<form-login login-page="/login.jsp"/>
</http>
<authentication-provider>
<jdbc-user-service data-source-ref="dataSource" />
</authentication-provider>
However, I can't even navigate to the login page and get the following error in the log:
WARNING: The login page is being
protected by the filter chain, but you
don't appear to have anonymous
authentication enabled. This is almost
certainly an error.
I've tried changing the ROLE_ANONYMOUS to IS_AUTHENTICATED_ANONYMOUSLY, changing the login-page to index.jsp, login.htm, and adding different intercept-url values, but I can't get it so the login page is accesible and security applies to the other pages. What do I have to change to avoid this loop?
The problem was I was missing the
<anonymous />
tag in the http section of the security-config.xml file so I wasn't able to get to the login page anonymously. Once I added this, I was able to get to the login page and authenticate.
You should set auto-config attribute:
<http auto-config="true">
<intercept-url ... />
...
</http>
EDIT:
To avoid problems with multiple UserDetailsService you probably can replace your <authentication-provider> declaration by something like this:
<authentication-provider user-service-ref = "userService" />
<jdbc-user-service id = "userService" data-source-ref="dataSource" />
<intercept-url pattern="/login*" access="ROLE_ANONYMOUS" />
you could have replaced that with
<intercept-url pattern="/login*" filter="none" />
because spring security is right, it doesn't make any sense to protect the login page
you can use another sec:http section
<sec:http pattern="/login" security="none" />
or you can use
<sec:intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" />

Resources