I implemented spring security 3.2.5 but unfortunately #PreAuthorize does not work on classes and methods. As I read from the documentations, #PreAuthorize should allow methods and classes to work if user has specified role inside the annotation but I am able to run all the methods or classes without any difference of roles. You can see security-config.xml and security.context.xml and my class where I declared #PreAuthorize annotation below. I would be glad if you can help me about this problem.
security-config.xml
<?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.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<http pattern="/securityNone" security="none" />
<http use-expressions="true">
<intercept-url pattern="/**" access="isAuthenticated()" />
<http-basic />
</http>
<global-method-security pre-post-annotations="enabled" />
<authentication-manager>
<authentication-provider>
<user-service>
<user name="alperk" password="123" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
security-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://www.springframework.org/schema/security"
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">
<bean id="defaultAuthEventPublisher" class="org.springframework.security.authentication.DefaultAuthenticationEventPublisher"/>
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<property name="providers">
<list>
<ref bean="authenticationProvider"/>
</list>
</property>
<property name="authenticationEventPublisher" ref="defaultAuthEventPublisher"/>
</bean>
<!-- Authentication service reference -->
<bean id="customUserDetailsService" class="tr.com.sistek.utak.authentication.AuthenticationUserDetailsService"/>
<!-- Authentication yapilirken MD5 password sifreleme kullaniliyor -->
<bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder"/>
<bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="customUserDetailsService"/>
<!--<property name="passwordEncoder" ref="passwordEncoder"/>-->
</bean>
<bean id="authenticationSuccessHandler" class="tr.com.sistek.utak.authentication.CustomAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/faces/private/MainMenu.jsf"/>
</bean>
<bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
<property name="exceptionMappings">
<props>
<prop key="org.springframework.security.authentication.BadCredentialsException">/login-failure.jsf?err=HATALI_PWD</prop>
<prop key="org.springframework.security.authentication.CredentialsExpiredException">/change-password.jsf</prop>
<prop key="org.springframework.security.authentication.LockedException">/login-failure.jsf?err=HESAP_KILITLI</prop>
<prop key="org.springframework.security.authentication.DisabledException">/login-failure.jsf?err=HESAP_PASIF</prop>
</props>
</property>
</bean>
<bean id="accessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage" value="/error401.jsf"/>
</bean>
<!-- Login Esnasinda Girilen Bilgileri Kontrol Etmek Icin Kullanilmistir -->
<bean id="customPreAuthenticationLoginHandler" class="tr.com.sistek.utak.authentication.CustomPreAuthenticationLoginHandler">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
<property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
<property name="filterProcessesUrl" value="/j_security_check" />
<property name="sessionAuthenticationStrategy" ref="sas" />
<property name="postOnly" value="false" />
</bean>
<sec:http pattern="/assets/**" security="none"/>
<sec:http pattern="/images/**" security="none"/>
<sec:http pattern="/resources/**" security="none"/>
<sec:http pattern="/themes/**" security="none"/>
<sec:http pattern="/javax.faces.resource/**" security="none"/>
<sec:global-method-security
pre-post-annotations="enabled"
mode="aspectj"
proxy-target-class="true">
</sec:global-method-security>
<sec:http auto-config="true" use-expressions="true"
authentication-manager-ref="authenticationManager">
<sec:intercept-url pattern="/dashboard/**" access="isAuthenticated()"/>
<sec:custom-filter before="FORM_LOGIN_FILTER" ref="customPreAuthenticationLoginHandler"/>
<sec:form-login login-page="/login.jsf"
authentication-failure-handler-ref = "authenticationFailureHandler"
default-target-url="/faces/private/MainMenu.jsf"/>
<sec:access-denied-handler ref = "accessDeniedHandler"/>
<sec:logout invalidate-session="true"
logout-success-url="/login.jsf"
logout-url="/logout"/>
<sec:session-management invalid-session-url="/login.jsf" session-authentication-strategy-ref="sas"/>
<sec:custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
</sec:http>
<bean id="jsfRedirectStrategy" class="tr.com.sistek.utak.jsf.filter.JsfRedirectStrategy"/>
<bean id="httpSessionSecurityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/>
<!-- Authentication logout handler -->
<bean id="customAuthenticationLogoutHandler" class="tr.com.sistek.utak.authentication.CustomAuthenticationLogoutHandler"/>
<!-- ******************************************************************* -->
<!-- Concurrent Session Management Configuration-->
<!-- ******************************************************************* -->
<bean id="concurrencyFilter"
class="org.springframework.security.web.session.ConcurrentSessionFilter">
<property name="sessionRegistry" ref="sessionRegistry" />
<property name="expiredUrl" value="/session-expired.jsf" />
<!-- this permits redirection to session timeout page from javascript/ajax or http -->
<property name="redirectStrategy" ref="jsfRedirectStrategy" />
</bean>
<bean id="sas" class= "org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<property name="maximumSessions" value="1" />
<!-- <property name="alwaysCreateSession" value="true" />
<property name="exceptionIfMaximumExceeded" value="true" />-->
</bean>
<bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl" />
Bean :
#ManagedBean
#ViewScoped
#PreAuthorize("hasRole('ROLE_ADMIN')")
public class OrderDetView implements Serializable {
......
This is only my first thought:
Your annotations #ManagedBean and #ViewScoped indicate that you use a JSF Framework and maybe your OrderDetView bean ins just a JSF bean but not a Spring bean. But #PreAuthorize works only for Spring beans.
Related
I am trying to implement Oauth2 spring security with Spring 4.1
I am sending password, username , client_id and client_secret but still i get bad credentials.
the request i send is as follows:
http://localhost:8080/asset-manager/oauth/token?grant_type=password&client_id=restapp&client_secret=restapp&username=ankita&password=ankita
I have the following files
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:context="http://www.springframework.org/schema/context"
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.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-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd ">
<!-- 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="isFullyAuthenticated()" />
<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" />
<csrf disabled="true" />
</http>
<!-- This is where we tells spring security what URL should be protected
and what roles have access to them -->
<http pattern="/api/**" 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="/api/**" access="hasRole('ROLE_USER')" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<csrf disabled="true" />
</http>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test" />
</bean>
<bean id="requestFactory"
class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<constructor-arg name="clientDetailsService" ref="clientDetails" />
</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="authenticationManager" />
</bean>
<bean id="accessDecisionManager"
class="org.springframework.security.access.vote.AffirmativeBased"
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" />
<bean
class="org.springframework.security.web.access.expression.WebExpressionVoter"></bean>
</list>
</constructor-arg>
</bean>
<authentication-manager id="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<bean id="authenticationProcessingFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<!-- 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="ankita" password="ankita" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
<authentication-provider user-service-ref="clientDetailsUserService" />
</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="120" />
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<property name="tokenStore" ref="tokenStore" />
<property name="clientDetailsService" ref="clientDetails" />
<property name="requestFactory" ref="requestFactory" />
</bean>
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
<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="restapp"
authorized-grant-types="authorization_code,client_credentials"
authorities="ROLE_USER" scope="read,write,trust" secret="secret" />
<oauth:client client-id="restapp"
authorized-grant-types="password,authorization_code,refresh_token,implicit"
secret="restapp" scope="read,write,trust" authorities="ROLE_USER" />
</oauth:client-details-service>
<bean id="httpSessionSecurityContextRepository"
class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
<property name='allowSessionCreation' value='false' />
</bean>
<bean id="securityContextPersistenceFilter"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
<constructor-arg ref="httpSessionSecurityContextRepository" />
</bean>
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<constructor-arg>
<list>
<sec:filter-chain pattern="/**"
filters="securityContextPersistenceFilter" />
</list>
</constructor-arg>
</bean>
<sec:global-method-security
pre-post-annotations="enabled" proxy-target-class="true"
authentication-manager-ref="authenticationManager"
secured-annotations="enabled">
<!--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" />
And this is my pom.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/mvc-dispatcher-servlet.xml,
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring Security -->
<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>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
Unfortunately whenever i send a request it throws this:
{
"error": "invalid_grant",
"error_description": "Bad credentials"
}
Need Help !
You only need to pass the username, password (both of these are for the user, not the client), grant_type and client_id request params.
You must send an Authorization header, containing BASIC auth using the client ID as the username and the client secret as the password.
This is how you would do it in cURL for example:
$ curl -u restapp:restapp http://localhost:8080/asset-manager/oauth/token -d grant_type=password -d client_id=restapp
I had a similar issue when upgrading from Spring Security 4.0.4 to 4.1.1.
Try changing "alias" in your authentication-manager bean definition to "id":
<authentication-manager id="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider>
<user-service>
<user name="ankita" password="ankita" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
<authentication-provider user-service-ref="clientDetailsUserService" />
I found that for some reason the "alias" definition in the custom "authenticationManager" does not get recognized. When I changed "alias" to "id", my custom AuthenticationManager worked again.
I saw this issue when testing Spring Security 4.1.0, so I'm not sure what changed between Spring Security 4.0.4 and 4.1.0 that caused this to break.
I tried to search the release notes and issues in the Spring Security github, but couldn't find anything related to this. All I know is that this small fix worked for me.
Hope this helps.
I had to change some of the properties in spring-security.xml file with updated functionalities and also i override some of classes such as AuthenticationProvider and ClientDetailsService according to my use case, also i have used redis as my token store , you can replace it in memory token store
My updated spring-security.xml is:
<?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:context="http://www.springframework.org/schema/context"
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.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-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd ">
<!-- 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="isFullyAuthenticated()" method="POST"/>
<intercept-url pattern="/v1/access_token" access="isFullyAuthenticated()" method="POST"/>
<anonymous enabled="false" />
<http-basic entry-point-ref="oauthAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request
userService parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter"
after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<csrf disabled="true" />
</http>
<!-- This is where we tells spring security what URL should be protected
and what roles have access to them -->
<http pattern="/v1/**" create-session="stateless"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/v1/application/register" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/v1/application/{clientId}" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<csrf disabled="true" />
</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="authenticationManager" />
</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" />
<bean
class="org.springframework.security.web.access.expression.WebExpressionVoter" />
</list>
</constructor-arg>
</bean>
<authentication-manager id="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<!-- <authentication-provider user-service-ref="clientDetailsUserService"
/> -->
<authentication-provider ref="AuthenticationProvider" />
</authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetailsService" />
</bean>
<authentication-manager
xmlns="http://www.springframework.org/schema/security" alias="authenticationManager">
<authentication-provider ref="AuthenticationProvider" />
</authentication-manager>
<bean id="AuthenticationProvider"
class="com.timeinc.security.biz.client.security.impl.AuthenticationProviderImpl">
<property name="userService" ref="userService"></property>
</bean>
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore">
<constructor-arg name="connectionFactory" ref="redisConnectionFactory" />
</bean>
<!--create redis connection factory and set db 1 -->
<bean id="redisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${redisHost}" />
<property name="port" value="${redisPort}" />
<property name="password" value="${redisPassword}" />
<property name="database" value="${redisDatabase}" />
</bean>
<bean id="tokenServices" class="com.timeinc.security.biz.client.security.impl.DefaultTokenServicesImpl">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="accessTokenValiditySeconds" value="${accessTokenValiditySeconds}" />
<property name="refreshTokenValiditySeconds" value="${refreshTokenValiditySeconds}"></property>
<property name="clientDetailsService" ref="clientDetailsService" />
</bean>
<bean id="requestFactory"
class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<constructor-arg name="clientDetailsService" ref="clientDetailsService" />
</bean>
<bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<property name="tokenStore" ref="tokenStore" />
<property name="clientDetailsService" ref="clientDetailsService" />
<property name="requestFactory" ref="requestFactory" />
</bean>
<oauth:authorization-server
client-details-service-ref="clientDetailsService" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
<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" />
<bean id="clientDetailsService" class="com.timeinc.security.biz.client.security.impl.ClientDetailsServiceImpl">
<property name="appClient" ref="appClient"></property>
</bean>
<bean id="httpSessionSecurityContextRepository"
class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
<property name='allowSessionCreation' value='false' />
</bean>
<bean id="userService" class="com.timeinc.security.biz.client.security.impl.UserDetailsServiceImpl">
<property name="appClient" ref="appClient"></property>
</bean>
<bean id="securityContextPersistenceFilter"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
<constructor-arg ref="httpSessionSecurityContextRepository" />
</bean>
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<constructor-arg>
<list>
<sec:filter-chain pattern="/**"
filters="securityContextPersistenceFilter" />
</list>
</constructor-arg>
</bean>
<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>
Currently I use spring mvc oauth2 to secure my web application.
I tried to do curl -X POST "http://localhost:8080/project/oauth/token?client_id=the_client&grant_type=password&username=user&password=password&response_type=token"
I got reply.
{"error":"unauthorized","error_description":"There is no client authentication. Try adding an appropriate authentication filter."}
Then I checked the code of TokenEndpoint.java, It show the Principal is null.
The exception is Handling error: InsufficientAuthenticationException, There is no client authentication. Try adding an appropriate authentication filter.
Here is the 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:oauth2="http://www.springframework.org/schema/security/oauth2"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd">
<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" />
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint" />
<bean id="accessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler" />
<!--client -->
<bean id="clientDetailsService" class="oauth2.CustomJdbcClientDetailsService">
<constructor-arg index="0" ref="dataSource" />
</bean>
<bean id="clientDetailsUserDetailsService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetailsService" />
</bean>
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
<security:authentication-manager id="clientAuthenticationManager">
<security:authentication-provider
user-service-ref="clientDetailsUserDetailsService" />
</security:authentication-manager>
<oauth2:authorization-server
client-details-service-ref="clientDetailsService" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
<oauth2:authorization-code />
<oauth2:implicit />
<oauth2:refresh-token />
<oauth2:client-credentials />
<oauth2:password />
</oauth2:authorization-server>
<security:http pattern="/oauth/token" create-session="stateless">
<security:anonymous enabled="false" />
<security:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<security:custom-filter ref="clientCredentialsTokenEndpointFilter"
before="BASIC_AUTH_FILTER" />
<security:access-denied-handler ref="accessDeniedHandler" />
</security:http>
<!--client -->
<!--user -->
<bean id="userService" class="services.UserServicesImpl" />
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
user-service-ref="userService">
<!--<security:password-encoder hash="md5"/> -->
</security:authentication-provider>
</security:authentication-manager>
<!--user -->
<oauth2:resource-server id="mobileResourceServer"
resource-id="mobile-resource" token-services-ref="tokenServices" />
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
<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>
<security:http pattern="/rest/**" create-session="never"
entry-point-ref="clientAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager" use-expressions="false">
<security:anonymous enabled="false" />
<security:intercept-url pattern="/rest/**"
access="ROLE_DRIVER" />
<security:custom-filter ref="mobileResourceServer"
before="PRE_AUTH_FILTER" />
<security:access-denied-handler ref="accessDeniedHandler" />
</security:http>
I don't know why it is wrong, Please help me thanks.
You have to provide a query parameter named "client_secret" for the client authentication.
Url those assigned to access roles not working only blank page coming. Only few urls working those have filter="none".
No error or no exception coming.
Blank page coming after login.
Url like: /indexPage
/test/indexPage
securityContext.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:c="http://www.myPro.com/schema/system-config"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.3.xsd
http://www.myPro.com/schema/system-config http://www.myPro.com/schema/system-config/system-config-1.0.xsd">
<!-- enable method-level security via annotation -->
<sec:global-method-security secured-annotations="enabled" jsr250-annotations="disabled"/>
<!-- secure the web layer -->
<sec:http auto-config="false" entry-point-ref="myAuthenticationEntryPoint" lowercase-comparisons="false">
<sec:custom-filter position="FORM_LOGIN_FILTER" ref="customizedFormLoginFilter"/>
<sec:custom-filter after="FORM_LOGIN_FILTER" ref="rememberMeProcessingFilter"/>
<sec:custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="singleSignOnFilter"/>
<sec:custom-filter after="REMEMBER_ME_FILTER" ref="logoutFilter" />
<sec:intercept-url pattern="/login.jsp" filters="none" />
<sec:intercept-url pattern="/**" access="ROLE_USER" />
<sec:intercept-url pattern="/contract/ServiceContractPDFView.jsp" filters="none" />
<sec:intercept-url pattern="/admin/unsubscribe_sbpqm_newsletter.jsp" filters="none" />
<sec:intercept-url pattern="/admin/subscription_form.jsp" filters="none" />
<sec:intercept-url pattern="/admin/subscription_thankyou.jsp" filters="none" />
<sec:intercept-url pattern="/admin/related_analysts.jsp" filters="none" />
<sec:intercept-url pattern="/favicon.ico" filters="none" />
<sec:intercept-url pattern="/styles/**" filters="none" />
<sec:intercept-url pattern="/images/**" filters="none" />
<sec:intercept-url pattern="/qlogin.jsp" filters="none" />
<sec:intercept-url pattern="/qloginWait/**" filters="none" />
<sec:intercept-url pattern="/js/**" filters="none" />
<sec:intercept-url pattern="/scripts/**" filters="none" />
<sec:anonymous username="anonymousUser" granted-authority="ROLE_ANONYMOUS"/>
</sec:http>
<!--name of my authenticationManager is authenticationManager-->
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider user-service-ref="myUserDetailsService" />
</sec:authentication-manager>
<bean id="customizedFormLoginFilter" class="com.myPro.test.security.CustomAuthenticationProcessingFilter" >
<!--Authentication failed? take him to error page-->
<!--Here it is the custom authenticationManager, login magic goes here -->
<property name="authenticationManager" ref="myAuthenticationManager"/>
<property name="authenticationFailureHandler" ref="failureHandler"/>
<property name="authenticationSuccessHandler" ref="successHandler"/>
<property name="rememberMeServices" ref="rememberMeServices" />
<property name="allowSessionCreation" value="true" />
</bean>
<bean id="myAuthenticationManager" class="com.myPro.test.security.CustomAuthenticationManager" />
<bean id="loggerListener" class="org.springframework.security.access.event.LoggerListener"/>
<!--My authentication entry point, can be replaced easily if we are doing custom commence of invalid auths.-->
<bean id="myAuthenticationEntryPoint"
class="com.myPro.test.security.CustomAuthenticationEntryPoint" >
<property name="loginFormUrl" value="/login.jsp"/>
</bean>
<bean id="successHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/indexCustomer.jsp"/>
</bean>
<bean id="failureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login.jsp?login_error=1"/>
</bean>
<!-- Override RememberMeProcessingFilter to allow application of other business logic (update login count when user returns to the site -->
<bean id="rememberMeProcessingFilter" class="com.myPro.test.security.CustomRememberMeProcessingFilter">
<property name="rememberMeServices" ref="rememberMeServices"/>
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="signleSignOnService" class="com.myPro.sage.sso.dynamo.SsoDbStorage">
</bean>
<bean id="singleSignOnFilter"
class="com.myPro.test.spring.SingleSignOnFilter">
<property name="signleSignOnService" ref="signleSignOnService"/>
<!--<property name="authenticationProviderFacade" ref="authenticationProviderFacade"/>-->
<property name="userService" ref="myProUserServiceImpl"/>
<property name="ssoUserUrl">
<value>/sso</value>
</property>
<!-- Code Review Starts -->
<property name="ssoTargetUrl">
<value>/search/ServiceContractSearch.do</value>
</property>
<!-- Code Review Ends -->
<property name="ssoFailureUrl">
<value>/login.jsp</value>
</property>
<property name="order" value="123456"/>
</bean>
<!-- Remember me Authentication Defines which remember me implementation to use - in this case using a database table to log 'remembered' tokens -->
<bean id="myUserDetailsService" class="com.myPro.test.security.CustomUserDetailsService" > </bean>
<bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
<property name="tokenRepository" ref="jdbcTokenRepository" />
<property name="userDetailsService" ref="myUserDetailsService" />
<property name="key" value="springRocks" />
<property name="alwaysRemember" value="false" />
</bean>
<!-- Uses a database table to maintain a set of persistent login data -->
<bean id="jdbcTokenRepository" class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
<property name="createTableOnStartup" value="false" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
<!-- <sec:custom-authentication-provider/> -->
<property name="key" value="springRocks"/>
</bean>
<bean id="securityContextLogoutHandler" class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" >
<property name="invalidateHttpSession" value="true" />
</bean>
<bean id="mySecurityContextHandler" class="com.myPro.test.security.CustomSecurityContextLogoutHandler"/>
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="/" />
<constructor-arg>
<list>
<ref bean="mySecurityContextHandler" />
<ref bean="rememberMeServices" />
<ref bean="securityContextLogoutHandler" />
</list>
</constructor-arg>
</bean>
<bean id="authenticationLoggerListener" class="org.springframework.security.access.event.LoggerListener"/>
<bean id="_sessionFixationProtectionFilter" class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
<property name="migrateSessionAttributes" value="true" />
</bean>
</beans>
There are 2 things wrong.
First the order of the url-intercept patterns is important. The order in which they are defined is also the order in which they are consulted! Having a /** makes every url-intercept element after that useless. So a `/** should always come last.
Second in newer Spring Security versions you shouldn't be using the filters="none" anymore. You should create separate <sec:http /> elements for those. See this part of the Spring Security Reference guide.
<sec:http pattern="/login.jsp" security="none" />
<sec:http pattern="/js/**" security="none" />
<sec:http pattern="/scripts/**" security="none" />
<!--- All other patterns here. -->
I practice spring security oauth2 with client credentials grant type
Here is my xml files for spring security oauth
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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 http://www.springframework.org/schema/security/spring-security-4.0.xsd
http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<sec:debug />
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:client-credentials />
</oauth:authorization-server>
<sec:authentication-manager alias="clientAuthenticationManager">
<sec:authentication-provider
user-service-ref="clientDetailsUserService">
</sec:authentication-provider>
</sec:authentication-manager>
<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"
before="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<oauth:resource-server id="resourceServerFilter"
resource-id="rest_server" token-services-ref="tokenServices" />
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="abc" authorized-grant-types="client_credentials"
authorities="ROLE_RESTREAD" secret="123" />
</oauth:client-details-service>
<http pattern="/**" 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="/prot**" access="ROLE_RESTREAD"
method="GET" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<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="false" />
<property name="clientDetailsService" ref="clientDetails" />
<property name="accessTokenValiditySeconds" value="400000" />
<property name="refreshTokenValiditySeconds" value="0" />
</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.AuthenticatedVoter" />
<bean
class="org.springframework.security.web.access.expression.WebExpressionVoter" />
</list>
</constructor-arg>
</bean>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="theRealm" />
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="theRealm/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<sec:global-method-security
pre-post-annotations="enabled" proxy-target-class="true">
<sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
</beans>
And I test on mac terminal :
curl -X -v -d 'client_id=abc&client_secret=123&grant_type=client_credentials' -X POST "http://localhost:8080/WiBDA_User/oauth/token"
But got error :
{"error":"access_denied","error_description":"Expected CSRF token not found. Has your session expired?"}
Please tell me what's wrong??
Thank you.
As of Spring Security 4.0, CSRF protection is enabled by default with XML configuration. If you would like to disable CSRF protection, the corresponding XML configuration can be seen below.
<http>
<csrf disabled="true"/>
</http>
Source : http://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html#csrf-configure
UPDATE : Please update your code to the new java-config, it is easy to understand and configure.
I'm trying to set up the LDAP Spring Security. And I've stucked with some strange exception:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_filterChainList'
...
No UserDetailsService registered
My security-config.xml looks like this:
<?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:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">
<sec:global-method-security secured-annotations="enabled"
access-decision-manager-ref="accessDecisionManager" />
<sec:http auto-config="true">
<sec:intercept-url pattern="/css/**" filters="none" />
<sec:intercept-url pattern="/js/**" filters="none" />
<sec:intercept-url pattern="/img/**" filters="none" />
<sec:intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<sec:intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" method="POST" />
<sec:intercept-url pattern="/uzivatel/registrace" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<sec:intercept-url pattern="/**" access="ROLE_UZIVATEL" />
<sec:form-login default-target-url="/vlakna" login-page="/login" />
</sec:http>
<bean id="accessDecisionManager" class="org.springframework.security.vote.ConsensusBased">
<property name="decisionVoters">
<list>
<ref bean="rightsAccessDecisionVoter" />
</list>
</property>
</bean>
<bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="ldap://111.111.111.111"/>
<property name="userDn" value="cn=auth-user,ou=System,dc=sh,dc=company,dc=com"/>
<property name="password" value="secret"/>
</bean>
<bean id="ldapAuthProvider" class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
<sec:custom-authentication-provider/>
<constructor-arg>
<bean class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
<constructor-arg ref="contextSource"/>
<property name="userSearch">
<bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value="ou=People,dc=sh,dc=company,dc=com"/>
<constructor-arg index="1" value="(uid={0})"/>
<constructor-arg index="2" ref="contextSource" />
</bean>
</property>
<property name="userDnPatterns">
<list><value>uid={0},ou=people</value></list>
</property>
<property name="userAttributes">
<list><value></value></list>
</property>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="cz.rohan.dusps.services.UzivatelAuthoritiesPopulator" />
</constructor-arg>
</bean>
<bean id="rightsAccessDecisionVoter" class="com.company.RightsAccessDecisionVoter" />
</beans>
I thought that it should take "ldapAuthProvider" as an user details service but it doesn't. Does anybody see any problem in my config?
Thanks for any help,
Mateo
I think...
<bean id="ldapAuthProvider" class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
<security:custom-authentication-provider />
// MISSING ABOVE
<property name="userDetailsService" ref="ldapUserDetailsService" />
.....