An Authentication object was not found in the SecurityContext in oauth2 - spring-security

I have a project which uses spring security oauth2 for secured connections.Below is my spring configuration file.
spring-security.xml :
<?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:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:sec="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd ">
<!-- #author Nagesh.Chauhan(neel4soft#gmail.com) -->
<!-- This is default url to get a token from OAuth -->
<http pattern="/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" />
<!-- include this only if you need to authenticate clients via request
parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter"
after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<!-- This is where we tells spring security what URL should be protected
and what roles have access to them -->
<http pattern="/protected/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/protected/**" access="ROLE_APP" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test" />
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
<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>
<authentication-manager id="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<!-- This is simple authentication manager, with a hardcoded user/password
combination. We can replace this with a user defined service to get few users
credentials from DB -->
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider>
<user-service>
<user name="user1" password="user1" authorities="ROLE_APP" />
</user-service>
</authentication-provider>
</authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<!-- This defined token store, we have used inmemory tokenstore for now
but this can be changed to a user defined one -->
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" />
<!-- This is where we defined token based configurations, token validity
and other things -->
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="accessTokenValiditySeconds" value="3600" />
<property name="refreshTokenValiditySeconds" value="5270400"></property>
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<bean id="oAuth2RequestFactory"
class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<constructor-arg ref="clientDetails"/>
</bean>
<bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<property name="tokenStore" ref="tokenStore" />
<property name="requestFactory" ref="oAuth2RequestFactory"/>
</bean>
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler" authorization-endpoint-url="/protected" token-endpoint-url="/oauth/token">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
resource-id="test" token-services-ref="tokenServices" />
<oauth:client-details-service id="clientDetails">
<!-- client -->
<oauth:client client-id="client1"
authorized-grant-types="authorization_code,client_credentials"
authorities="ROLE_APP" scope="read,write,trust" secret="secret" />
<oauth:client client-id="client1"
authorized-grant-types="password,authorization_code,refresh_token,implicit"
secret="client1" authorities="ROLE_APP" />
</oauth:client-details-service>
<sec:global-method-security
pre-post-annotations="enabled" proxy-target-class="true">
<!--you could also wire in the expression handler up at the layer of the
http filters. See https://jira.springsource.org/browse/SEC-1452 -->
<sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
</beans>
When i request for oauth access token using the below request am getting the access and refresh token as below.
Request is
curl -X POST http://localhost:8080/SaveItMoneyOauth/oauth/token -H “Accept: application/json” -d "grant_type=password&client_id=client1&client_secret=client1&username=user1&password=user1&scope=read,write,trust"
Response is :
{"value":"4796a04a-2266-4184-a1be-e4248cea7ba8","expiration":"Jul 11, 2016 12:15:34 PM","tokenType":"bearer","refreshToken":{"expiration":"Sep 10, 2016 11:15:34 AM","value":"87509989-0ea9-4372-87aa-22290ae0c98e"},"scope":["read,write,trust"],"additionalInformation":{}}curl: (6) Could not resolve host: application
Then when i i requested for the protected resources using below request i am getting "An Authentication object was not found in the SecurityContext" as error.
Request is :
curl -H "access_token=4796a04a-2266-4184-a1be-e4248cea7ba8" "http://localhost:8080/SaveItMoneyOauth/protected/users/api"
I am using "2.0.7.RELEASE" as the oauth2 library.
How to solve this error.Please help me.

Your CURL command is wrong, you need to provide the access token in the Authorization header. Try this:
curl -H "Authorization: Bearer 4796a04a-2266-4184-a1be-e4248cea7ba8" "http://localhost:8080/SaveItMoneyOauth/protected/users/api"

Related

Spring Security OAuth 2.0 - Exception Translator and Exception Renderer not invoked. I get html response with an error instead of JSON

I want to secure my REST API with OAuth 2.0 using Spring Security OAuth 2.0. In /oauth/token request I want to process a request to check if it contains required, custom data. I added a filter (OAuth2CookieFilter) in order to do it. If this information is not available, I want to throw an exception with a custom JSON message. In order to do this, I implemented a custom exception translator and exception renderer and added them to the authentication entrypoint. The problem is that when I throw an exception (which inherits from OAuth2Exception) in OAuth2CookieFilter, my exception handling code is not invoked. Instead I get an html page with stack trace in response. Below is my XML config; I stripped it from unnecessary code. Do you know what is wrong?
<security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled" />
<mvc:cors>
<mvc:mapping path="/**" />
</mvc:cors>
<bean id="oAuth2CookieFilter" class="org.mycompany.services.security.OAuth2CookieFilter" />
<bean id="corsHandler" class="org.mycompany.services.security.CORSFilter" />
<bean id="putFormFilter" class="org.springframework.web.filter.HttpPutFormContentFilter" />
<security:http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager">
<security:anonymous enabled="false" />
<security:intercept-url pattern="/oauth/token" access="hasRole('ROLE_TRUSTED_CLIENT')" />
<security:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<security:custom-filter ref="oAuth2CookieFilter" after="PRE_AUTH_FILTER" />
<security:custom-filter ref="corsHandler" before="PRE_AUTH_FILTER"/>
<security:custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<security:access-denied-handler ref="oauthAccessDeniedHandler" />
<security:csrf disabled="true" />
</security:http>
<security:authentication-manager id="clientAuthenticationManager">
<security:authentication-provider user-service-ref="clientDetailsUserService" />
</security:authentication-manager>
<bean id="clientDetailsUserService" class="org.mycompany.services.security.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="clientDetails" class="org.mycompany.services.security.ClientDetailsService"/>
<bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
<bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="server" />
<property name="typeName" value="Basic" />
<property name="exceptionTranslator" ref="oauthErrorHandler" />
<property name="exceptionRenderer" ref="oauthExceptionRender" />
</bean>
<!-- Protected resources -->
<security:http pattern="/**" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint">
<security:anonymous enabled="false" />
<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<security:custom-filter ref="putFormFilter" position="FIRST"/>
<security:custom-filter ref="corsHandler" before="PRE_AUTH_FILTER"/>
<security:custom-filter ref="resourceServerFilter" after="PRE_AUTH_FILTER" />
<security:access-denied-handler ref="oauthAccessDeniedHandler" />
<security:csrf disabled="true" />
</security:http>
<bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="server" />
<property name="exceptionTranslator" ref="oauthErrorHandler" />
<property name="exceptionRenderer" ref="oauthExceptionRender" />
</bean>
<bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
<property name="exceptionTranslator" ref="oauthErrorHandler" />
<property name="exceptionRenderer" ref="oauthExceptionRender" />
</bean>
<bean id="oauthErrorHandler" class="org.mycompany.services.security.exception.OauthErrorHandler"/>
<bean id="oauthExceptionRender" class="org.mycompany.services.security.exception.OauthExceptionRenderer"/>
<!-- I THINK THIS CODE BELOW IS NOT RELATED TO THE PROBLEM BUT I PASTE IT ANYWAY -->
<bean id="encoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder">
<constructor-arg value="${passwordSecret}"/>
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="userDetailsService">
<security:password-encoder ref="encoder" />
</security:authentication-provider>
</security:authentication-manager>
<bean id="userDetailsService" class="org.mycompany.services.security.UserDetailsService"/>
<!-- Token Store -->
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JwtTokenStore" >
<constructor-arg ref="JwttokenConverter"></constructor-arg>
</bean>
<bean id="approvalStore" class="org.springframework.security.oauth2.provider.approval.TokenApprovalStore">
<property name="tokenStore" ref="tokenStore" />
</bean>
<bean id="JwttokenConverter" class="org.mycompany.services.security.TokenEncoder">
<property name="signingKey" value="${signingKey}"></property>
</bean>
<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices" >
<property name="tokenStore" ref="tokenStore" />
<property name="tokenEnhancer" ref="JwttokenConverter" />
<property name="supportRefreshToken" value="true" />
<property name="clientDetailsService" ref="clientDetails" />
<property name="accessTokenValiditySeconds" value="300" />
</bean>
<bean id="oAuth2RequestFactory" class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="userApprovalHandler" class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<property name="clientDetailsService" ref="clientDetails" />
<property name="tokenStore" ref="tokenStore" />
<property name="requestFactory" ref="oAuth2RequestFactory" />
</bean>
<oauth2:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices" user-approval-handler-ref="userApprovalHandler">
<oauth2:authorization-code />
<oauth2:implicit />
<oauth2:refresh-token />
<oauth2:client-credentials />
<oauth2:password authentication-manager-ref="authenticationManager"/>
</oauth2:authorization-server>
<oauth2:resource-server id="resourceServerFilter" resource-id="server" token-services-ref="tokenServices" token-extractor-ref="tokenExtractor"/>
<bean id="tokenExtractor" class="org.mycompany.services.security.TokenExtractor"/>
<oauth2:expression-handler id="oauthExpressionHandler" />
<oauth2:web-expression-handler id="oauthWebExpressionHandler" />

Spring Security Oauth 2.0.4.RELEASE - The requested resource is not available

When calling GET /oauth/token?grant_type=password&client_id=web&client_secret=secret&username=test&password=test
The obtained response is a 404 not found "The requested resource is not available"
When calling GET /oauth/token?grant_type=password&client_id=web&client_secret=&username=test&password=test
The response is {"error":"invalid_client","error_description":"Bad client credentials"}, that is right because the client secret has not been provided
the full log of the first error (or unexpected behavior) is here:
https://gist.github.com/anonymous/02e032cf76749732d7af
I'm using spring security version 3.2.5.RELEASE and spring security oath version 2.0.4.RELEASE
Do you have any idea of what i'm doing wrong
my spring-security configuration:
<?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:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<sec:http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager">
<sec:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<sec:anonymous enabled="false" />
<sec:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<sec:custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
</sec:http>
<sec:http pattern="/user/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint">
<sec:anonymous enabled="false" />
<sec:intercept-url pattern="/user/**" access="ROLE_USER" />
<sec:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
</sec:http>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test" />
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
</bean>
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
<sec:authentication-manager id="clientAuthenticationManager">
<sec:authentication-provider user-service-ref="clientDetailsUserService" />
</sec:authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="web" authorized-grant-types="password,authorization_code,refresh_token,implicit"
authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" scope="read,write,trust" access-token-validity="60" secret="secret" />
<oauth:client client-id="web2" authorized-grant-types="client_credentials" authorities="ROLE_CLIENT"
scope="read" secret="secret" />
</oauth:client-details-service>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider>
<sec:user-service>
<sec:user name="test" password="test" authorities="ROLE_USER"/>
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:authorization-code />
<oauth:implicit/>
<oauth:refresh-token/>
<oauth:client-credentials />
<oauth:password authentication-manager-ref="authenticationManager"/>
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter" resource-id="test" token-services-ref="tokenServices" />
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" />
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore"/>
<property name="supportRefreshToken" value="true"/>
<property name="accessTokenValiditySeconds" value="900000000"/>
<property name="clientDetailsService" ref="clientDetails" />
</bean>
</beans>
I finally managed to get it work. The problem was in the web.xml. I was configuring my dispatcher servlet to map extensions requests:
<servlet>
<servlet-name>base</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>base</servlet-name>
<url-pattern>*.json</url-pattern>
</servlet-mapping>
so the servlet was unable to process /oauth/token requests. Switching it back to:
<usl-pattern>/</url-pattern>
made oauth flows working.

Spring security 3.0 remember me functionality

I have been trying to implement spring security 3.0 remember me service in my application but unfortunately couldn't get it working.
I didn't find any specific example related to this, not even in spring documentation. It would be nice if somebody can give a working example code. Please find code of my spring-security.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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">
<security:http entry-point-ref="myAuthenticationEntryPoint">
<security:session-management
session-fixation-protection="newSession" />
<security:custom-filter position="FORM_LOGIN_FILTER"
ref="processingFilter" />
<security:logout logout-url="/logout"
logout-success-url="/login" />
<security:intercept-url pattern='/index.jsp'
filters='none' />
<security:intercept-url pattern='/login*'
filters='none' />
<security:remember-me key="springrocks" />
<security:intercept-url pattern='/admin/**'
access="ROLE_ADMIN" />
</security:http>
<security:authentication-manager>
<security:authentication-provider
ref="myAuthenticationProvider"></security:authentication-provider>
</security:authentication-manager>
<bean id="myAuthenticationProvider"
class="example.AuthenticationProviderExtended">
</bean>
<bean id="authenticationManager" class="example.AuthenticationManagerExtended" />
<bean id="processingFilter" class="example.FormBasedProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="usernameParameter" value="username" />
<property name="passwordParameter" value="password" />
<property name="allowSessionCreation" value="true" />
<property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler" />
<property name="authenticationSuccessHandler" ref="simpleUrlAuthenticationSuccessHandler" />
<property name="filterProcessesUrl" value="/performLogin" />
</bean>
<bean id="simpleUrlAuthenticationFailureHandler" class="example.AuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login"></property>
</bean>
<bean id="simpleUrlAuthenticationSuccessHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/home" />
</bean>
<bean id="myAuthenticationEntryPoint"
class="example.CustomAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login" />
</bean>
<bean id="rememberMeFilter"
class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<property name="rememberMeServices" ref="rememberMeServices" />
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="rememberMeServices"
class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="myUserDetailsService" />
<property name="key" value="springRocks" />
</bean>
<bean id="rememberMeAuthenticationProvider"
class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
<property name="key" value="springRocks" />
</bean>
<bean id="myUserDetailsService" class="example.MyCustomeUserDetailsService">
</bean>
</beans>
Please look the Spring Security documentation here:
http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#remember-me-hash-token
You need to make sure your form contains a checkbox (or other types of input with) the remember me attribute name
<input type="checkbox" name="_spring_security_remember_me"/>
This attribute is configurable via remember-me-parameter on xml, eg:
<remember-me remember-me-parameter="please_remember"/>

Spring Security CAS causes redirect loop

I am using CAS SSO for my application to authenticate the users. But just after the login on the CAS login page, my application web page throws redirect loop error.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<security:http entry-point-ref="casEntryPoint"
auto-config="true">
<security:intercept-url pattern="/**" access="ROLE_USER" />
<security:custom-filter position="CAS_FILTER"
ref="casFilter"></security:custom-filter>
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
ref="casAuthenticationProvider" />
</security:authentication-manager>
<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
<property name="service" value="http://127.0.0.1:8888/pp.html?gwt.codesvr=127.0.0.1:9997" />
<property name="sendRenew" value="false" />
</bean>
<bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="casEntryPoint"
class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<property name="loginUrl" value="https://seqdws1/cas/login" />
<property name="serviceProperties" ref="serviceProperties" />
</bean>
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<property name="userDetailsService" ref="userService" />
<property name="serviceProperties" ref="serviceProperties" />
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<constructor-arg index="0" value="https://seqdws1/cas" />
</bean>
</property>
<property name="key" value="cas" />
</bean>
<security:user-service id="userService">
<security:user name="joe" password="joe" authorities="ROLE_USER" />
</security:user-service>
</beans>
Do i have to implementation pre auth scenario. I am very new to this spring-security. Can somebody explain what am i missing here.

How can I use a custom configured RememberMeAuthenticationFilter in spring security?

I want to use a slightly customized rememberme functionality with spring security (3.1.0).
I declare the rememberme tag like this:
<security:remember-me key="JNJRMBM" user-service-ref="gymUserDetailService" />
As I have my own rememberme service I need to inject that into the RememberMeAuthenticationFilter which I define like this:
<bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<property name="rememberMeServices" ref="gymRememberMeService"/>
<property name="authenticationManager" ref="authenticationManager" />
</bean>
I have spring security integrated in a standard way in my web.xml:
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
Everything works fine, except that the RememberMeAuthenticationFilter uses the standard RememberMeService, so I think that my defined RememberMeAuthenticationFilter is not being used.
How can I make sure that my definition of the filter is being used?
Do I need to create a custom filterchain?
And if so, how can I see my current "implicit" filterchain and make sure I use the same one except my RememberMeAuthenticationFilter instead of the default one?
Thanks for any advice and/or pointers!
Here the complete spring-security.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:http pattern="/_ui/**" security="none" />
<!-- Default security config -->
<security:http disable-url-rewriting="true">
<security:anonymous username="anonymous" granted-authority="ROLE_ANONYMOUS" />
<!-- session stealing is prevented by using secure GUID cookie -->
<security:session-management session-fixation-protection="none" />
<!-- SSL / AUTHENTICATED pages -->
<security:intercept-url pattern="/my-account*" access="ROLE_CUSTOMERGROUP" requires-channel="https" />
<security:intercept-url pattern="/my-account/**" access="ROLE_CUSTOMERGROUP" requires-channel="https" />
<!-- SSL / ANONYMOUS pages Login pages need to be SSL, but occur before authentication -->
<security:intercept-url pattern="/login" requires-channel="https" />
<security:intercept-url pattern="/login/**" requires-channel="https" />
<security:intercept-url pattern="/register" requires-channel="https" />
<security:intercept-url pattern="/register/**" requires-channel="https" />
<security:intercept-url pattern="/j_spring_security_check" requires-channel="https" />
<security:intercept-url pattern="/logout" requires-channel="https" />
<!-- MiniCart and CartPopup can occur on either secure or insecure pages -->
<security:intercept-url pattern="/cart/rollover/*" requires-channel="any" />
<security:intercept-url pattern="/cart/miniCart/*" requires-channel="any" />
<security:intercept-url pattern="/cart/show" requires-channel="any" />
<security:intercept-url pattern="/cart/lightboxmybag" requires-channel="any" />
<security:intercept-url pattern="/cart/remove/*" requires-channel="any" />
<security:intercept-url pattern="/cart/update/*" requires-channel="any" />
<security:intercept-url pattern="/cart/getProductSizes/**" requires-channel="any" />
<security:intercept-url pattern="/cart/getShippingMethods" requires-channel="any" />
<security:intercept-url pattern="/cart/setShippingMethod" requires-channel="any" />
<security:intercept-url pattern="/cart/applyVoucherDiscount" requires-channel="any" />
<security:intercept-url pattern="/cart/removeVoucherDiscount" requires-channel="any" />
<security:intercept-url pattern="/checkout/**" requires-channel="https" />
<!-- product suggest -->
<security:intercept-url pattern="/suggest*" requires-channel="any" />
<!-- cybersource response -->
<security:intercept-url pattern="/cybersource/response" requires-channel="any" />
<security:intercept-url pattern="/cybersource/csResponse" requires-channel="http" />
<!-- regions -->
<security:intercept-url pattern="/regions*" requires-channel="any" />
<security:intercept-url pattern="/regions/*" requires-channel="any" />
<!-- popup links -->
<security:intercept-url pattern="/popupLink/*" requires-channel="any" />
<!-- addresses -->
<security:intercept-url pattern="/my-addresses*" requires-channel="any" />
<security:intercept-url pattern="/my-addresses/**" requires-channel="any" />
<security:intercept-url pattern="/search/autocompleteSecure/**" requires-channel="https" />
<!-- OPEN / ANONYMOUS pages Run all other (public) pages openly. Note that while credentials are secure, the session id can be sniffed.
If this is a security concern, then this line should be re-considered -->
<security:intercept-url pattern="/**" requires-channel="any" method="POST" /> <!-- Allow posts on either secure or insecure -->
<security:intercept-url pattern="/**" requires-channel="http" /> <!-- Everything else should be insecure -->
<security:form-login
login-page="/login"
authentication-failure-handler-ref="loginAuthenticationFailureHandler"
authentication-success-handler-ref="loginGuidAuthenticationSuccessHandler" />
<security:logout logout-url="/logout" success-handler-ref="logoutSuccessHandler" />
<security:port-mappings>
<security:port-mapping http="#{configurationService.configuration.getProperty('tomcat.http.port')}"
https="#{configurationService.configuration.getProperty('tomcat.ssl.port')}" />
<security:port-mapping http="80" https="443" />
<!--security:port-mapping http="#{configurationService.configuration.getProperty('proxy.http.port')}"
https="#{configurationService.configuration.getProperty('proxy.ssl.port')}" /-->
</security:port-mappings>
<security:request-cache ref="httpSessionRequestCache" />
<security:remember-me key="JNJRMBM" user-service-ref="gymUserDetailService" />
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="acceleratorAuthenticationProvider" />
</security:authentication-manager>
<bean id="acceleratorAuthenticationProvider" class="org.jnj.storefront.security.AcceleratorAuthenticationProvider"
scope="tenant">
<property name="userDetailsService" ref="gymUserDetailService" />
<property name="adminGroup" value="ROLE_ADMINGROUP"/>
<property name="userService" ref="userService"/>
<property name="gymCustomerLoginService" ref="defaultGymCustomerLoginService"/>
</bean>
<bean id="gymUserDetailService" class="org.jnj.storefront.security.services.impl.GymCoreUserDetailsService" scope="tenant">
<property name="baseDao" ref="asyBaseDao" />
</bean>
<bean id="coreUserDetailsService" class="de.hybris.platform.spring.security.CoreUserDetailsService" scope="tenant" />
<bean id="guidCookieStrategy" class="org.jnj.storefront.security.impl.DefaultGUIDCookieStrategy"
scope="tenant">
<property name="cookieGenerator" ref="guidCookieGenerator" />
</bean>
<alias name="defaultGuidCookieGenerator" alias="guidCookieGenerator"/>
<bean id="defaultGuidCookieGenerator" class="org.jnj.storefront.security.cookie.EnhancedCookieGenerator" scope="tenant">
<property name="cookieSecure" value="true" />
<property name="cookieName" value="acceleratorSecureGUID" />
<property name="httpOnly" value="false"/>
<!-- if context allows a httpOnly adjust to true -->
</bean>
<bean id="autoLoginStrategy" class="org.jnj.storefront.security.impl.DefaultAutoLoginStrategy" scope="tenant">
</bean>
<bean id="httpSessionRequestCache" class="org.jnj.storefront.security.impl.WebHttpSessionRequestCache"
scope="tenant" />
<bean id="loginUserType" class="org.jnj.storefront.security.impl.LoginUserTypeBean" scope="tenant" />
<bean id="redirectStrategy" class="org.springframework.security.web.DefaultRedirectStrategy" scope="tenant" />
<!-- Login Success Handlers -->
<bean id="loginGuidAuthenticationSuccessHandler" class="org.jnj.storefront.security.GUIDAuthenticationSuccessHandler" scope="tenant">
<property name="authenticationSuccessHandler" ref="loginAuthenticationSuccessHandler" />
<property name="guidCookieStrategy" ref="guidCookieStrategy" />
</bean>
<bean id="loginAuthenticationSuccessHandler" class="org.jnj.storefront.security.StorefrontAuthenticationSuccessHandler" scope="tenant">
<property name="customerFacade" ref="customerFacade" />
<property name="defaultTargetUrl" value="/my-account"/>
<property name="useReferer" value="true"/>
<property name="alwaysUseDefaultTargetUrl" value="false"/>
<property name="requestCache" ref="httpSessionRequestCache" />
</bean>
<bean id="loginCheckoutGuidAuthenticationSuccessHandler" class="org.jnj.storefront.security.GUIDAuthenticationSuccessHandler" scope="tenant">
<property name="authenticationSuccessHandler" ref="loginCheckoutAuthenticationSuccessHandler" />
<property name="guidCookieStrategy" ref="guidCookieStrategy" />
<property name="defaultGymCartFacade" ref="gymCartFacade"/>
</bean>
<bean id="loginCheckoutAuthenticationSuccessHandler" class="org.jnj.storefront.security.StorefrontAuthenticationSuccessHandler" scope="tenant">
<property name="customerFacade" ref="customerFacade" />
<property name="defaultTargetUrl" value="/checkout/single/summary"/>
</bean>
<!-- Login Failure Handlers -->
<bean id="loginAuthenticationFailureHandler" class="org.jnj.storefront.security.LoginAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login?error=auth"/>
<property name="accountBlockedUrl" value="/login?error=blocked"/>
<property name="passwordMigrationUrl" value="/login?error=migration"/>
</bean>
<bean id="loginCheckoutAuthenticationFailureHandler" class="org.jnj.storefront.security.LoginAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login/checkout?error=auth"/>
<property name="accountBlockedUrl" value="/login/checkout?error=blocked"/>
<property name="passwordMigrationUrl" value="/login/checkout?error=migration"/>
</bean>
<!-- Logout Success Handler -->
<bean id="logoutSuccessHandler" class="org.jnj.storefront.security.StorefrontLogoutSuccessHandler" scope="tenant">
<property name="defaultTargetUrl" value="/?logout=true"/>
<property name="guidCookieStrategy" ref="guidCookieStrategy"/>
<property name="cmsSiteService" ref="cmsSiteService"/>
</bean>
<bean id="gymRememberMeService" class="org.jnj.storefront.security.cookie.DefaultRememberMeService" scope="tenant">
<property name="tokenService" ref="secureTokenService" />
<property name="rememberMeCookieGenerator" ref="defaultRememberMeCookieGenerator" />
</bean>
<bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<property name="rememberMeServices" ref="gymRememberMeService"/>
<property name="authenticationManager" ref="authenticationManager" />
</bean>
Did you try to have a look here (Spring Docs)?
They say:
"Don't forget to add your RememberMeServices implementation to your
UsernamePasswordAuthenticationFilter.setRememberMeServices() property,
include the RememberMeAuthenticationProvider in your
AuthenticationManager.setProviders() list, and add
RememberMeAuthenticationFilter into your FilterChainProxy (typically
immediately after your UsernamePasswordAuthenticationFilter)."
In your case, the RememberMeServices is gymRememberMeService; Do you have RememberMeAuthenticationProvider?
HTH
I ended up having to declare both the form-login and the remember-me tags explicitly and declare them in the filter chain.
so instead of the tag and the tag I had to declare the respective filters as beans, configure them accordingly and then define them in their respective position in the filterchain with the tag.
(If you use custom-filter tags and the explicit tags you get spring errors during startup time).
Here's what works for me:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:http pattern="/_ui/**" security="none" />
<!-- Default security config -->
<security:http disable-url-rewriting="true" entry-point-ref="gymAuthenticationEntryPoint">
<!-- using custom login filter config and rememberme filter config -->
<security:custom-filter ref="gymRememberMeFilter" position="REMEMBER_ME_FILTER"/>
<security:custom-filter ref="gymAuthenticationFilter" position="FORM_LOGIN_FILTER"/>
<security:anonymous username="anonymous" granted-authority="ROLE_ANONYMOUS" />
<!-- session stealing is prevented by using secure GUID cookie -->
<security:session-management session-fixation-protection="none" />
<!-- SSL / AUTHENTICATED pages -->
<security:intercept-url pattern="/my-account*" access="ROLE_CUSTOMERGROUP" requires-channel="https" />
<!-- omitting intercept definitions for readability -->
<!-- use explicit FORM_LOGIN_FILTER (see above) and entry-point (see entry-point-ref in http tag) instead of form-login definition
<security:form-login
login-page="/login"
authentication-failure-handler-ref="loginAuthenticationFailureHandler"
authentication-success-handler-ref="loginGuidAuthenticationSuccessHandler" />
-->
<security:logout logout-url="/logout" success-handler-ref="logoutSuccessHandler" />
<security:port-mappings>
<security:port-mapping http="#{configurationService.configuration.getProperty('tomcat.http.port')}"
https="#{configurationService.configuration.getProperty('tomcat.ssl.port')}" />
<security:port-mapping http="80" https="443" />
<!--security:port-mapping http="#{configurationService.configuration.getProperty('proxy.http.port')}"
https="#{configurationService.configuration.getProperty('proxy.ssl.port')}" /-->
</security:port-mappings>
<security:request-cache ref="httpSessionRequestCache" />
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="acceleratorAuthenticationProvider" />
<security:authentication-provider ref="rememberMeAuthenticationProvider" />
</security:authentication-manager>
<bean id="acceleratorAuthenticationProvider" class="org.jnj.storefront.security.AcceleratorAuthenticationProvider"
scope="tenant">
<property name="userDetailsService" ref="gymUserDetailService" />
<property name="adminGroup" value="ROLE_ADMINGROUP"/>
<property name="userService" ref="userService"/>
<property name="gymCustomerLoginService" ref="defaultGymCustomerLoginService"/>
</bean>
<bean id="gymUserDetailService" class="org.jnj.storefront.security.services.impl.GymCoreUserDetailsService" scope="tenant">
<property name="baseDao" ref="asyBaseDao" />
</bean>
<bean id="coreUserDetailsService" class="de.hybris.platform.spring.security.CoreUserDetailsService" scope="tenant" />
<!-- Login Success Handlers -->
<bean id="loginGuidAuthenticationSuccessHandler" class="org.jnj.storefront.security.GUIDAuthenticationSuccessHandler" scope="tenant">
<property name="authenticationSuccessHandler" ref="loginAuthenticationSuccessHandler" />
<property name="guidCookieStrategy" ref="guidCookieStrategy" />
</bean>
<bean id="loginAuthenticationSuccessHandler" class="org.jnj.storefront.security.StorefrontAuthenticationSuccessHandler" scope="tenant">
<property name="customerFacade" ref="customerFacade" />
<property name="defaultTargetUrl" value="/my-account"/>
<property name="useReferer" value="true"/>
<property name="alwaysUseDefaultTargetUrl" value="false"/>
<property name="requestCache" ref="httpSessionRequestCache" />
</bean>
<bean id="loginCheckoutGuidAuthenticationSuccessHandler" class="org.jnj.storefront.security.GUIDAuthenticationSuccessHandler" scope="tenant">
<property name="authenticationSuccessHandler" ref="loginCheckoutAuthenticationSuccessHandler" />
<property name="guidCookieStrategy" ref="guidCookieStrategy" />
<property name="defaultGymCartFacade" ref="gymCartFacade"/>
</bean>
<bean id="loginCheckoutAuthenticationSuccessHandler" class="org.jnj.storefront.security.StorefrontAuthenticationSuccessHandler" scope="tenant">
<property name="customerFacade" ref="customerFacade" />
<property name="defaultTargetUrl" value="/checkout/single/summary"/>
</bean>
<!-- Login Failure Handlers -->
<bean id="loginAuthenticationFailureHandler" class="org.jnj.storefront.security.LoginAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login?error=auth"/>
<property name="accountBlockedUrl" value="/login?error=blocked"/>
<property name="passwordMigrationUrl" value="/login?error=migration"/>
</bean>
<bean id="loginCheckoutAuthenticationFailureHandler" class="org.jnj.storefront.security.LoginAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login/checkout?error=auth"/>
<property name="accountBlockedUrl" value="/login/checkout?error=blocked"/>
<property name="passwordMigrationUrl" value="/login/checkout?error=migration"/>
</bean>
<!-- Logout Success Handler -->
<bean id="logoutSuccessHandler" class="org.jnj.storefront.security.StorefrontLogoutSuccessHandler" scope="tenant">
<property name="defaultTargetUrl" value="/?logout=true"/>
<property name="guidCookieStrategy" ref="guidCookieStrategy"/>
<property name="cmsSiteService" ref="cmsSiteService"/>
</bean>
<!-- remember me services -->
<bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="gymUserDetailService"/>
<property name="key" value="someprivatekey"/> <!-- must match the rememberMeAuthenticationProvider key -->
<property name="parameter" value="rememberMe" /><!-- must match the parameter in the login form -->
<property name="cookieName" value="JNJ_RMMBRM" />
<property name="useSecureCookie" value="false" /> <!-- if set to true "remember me" only gets detected when accessed via https -->
<property name="tokenValiditySeconds" value="31536000" /> <!-- 1 year -->
</bean>
<bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
<property name="key" value="someprivatekey"/>
</bean>
<bean id="gymRememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<property name="rememberMeServices" ref="rememberMeServices"/>
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationSuccessHandler" ref="loginGuidAuthenticationSuccessHandler"/>
</bean>
<!-- login filter and entry point -->
<bean id="gymAuthenticationFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="filterProcessesUrl" value="/j_spring_security_check"/>
<property name="rememberMeServices" ref="rememberMeServices"/>
<property name="authenticationSuccessHandler" ref="loginGuidAuthenticationSuccessHandler"/>
<property name="authenticationFailureHandler" ref="loginAuthenticationFailureHandler"/>
</bean>
<bean id="gymAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login"/>
</bean>
Spring Security 3.2+ supports the services-ref attribute on the remember-me element. So in your security config you would have:
<security:http xmlns="http://www.springframework.org/schema/security">
...
<remember-me services-ref="rememberMeServices" key="secret-key">
</security:http>
<bean id="rememberMeServices" class="com.example.MyRememberMeServices">
<constructor-arg index="0" value="secret-key" />
<constructor-arg index="1" ref="userDetailsService" />
<property name="tokenValiditySeconds" value="1000000" />
</bean>
where com.example.MyRememberMeServices is your custom RememberMeServices implementation class. Then messing with the filter chain, authentication managers, or anything else is no longer required.

Resources