Can someone please advise how to secure a web socket endpoint using Spring Security framework?
I have an application secured with Spring Security.
One of the endpoints is a web socket.
Inside the web socket handler I need to authenticate a user making a connection to the web socket.
Specifically, I need to acquire both userid and also zone/tenant id.
If I use tag sec:http for websocket endpoint in spring-security.xml (please see the file below), this does trigger a login, and then inside web socket's #onOpen(Session session) handler
when I invoke session.getUserPrincipal(), the returned principal has a correct username inside it.
However I also need zone/tenant-id information.
I am trying to use SecurityContextHolder.getContext().getAuthentication() which should contain it, but the call returns null.
Apparently, sec:http does not cause Authentication object to be created for web socket requests.
I had been referred to
http://docs.spring.io/autorepo/docs/spring-security/4.1.x/reference/html/websocket.html
http://docs.spring.io/autorepo/docs/spring-security/4.1.x/reference/html/appendix-namespace.html#nsa-websocket-security
that seems to advise that to get an authenticator with zone information in it for a websocket endpoint, I need to add the following section to spring-security.xml:
<sec:websocket-message-broker>
<sec:intercept-message pattern="/WebSocket.svc" access="isAuthenticated()" />
</sec:websocket-message-broker>
Yet, when I add it and trying to start the application it fails with the following traceback/message:
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Security namespace does not support decoration of element [websocket-message-broker]
Offending resource: ServletContext resource [/WEB-INF/spring-security.xml]
at org.springframework.beans.factory.parsing.FailFastProblemReporter.fatal(FailFastProblemReporter.java:60) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
at org.springframework.beans.factory.parsing.ReaderContext.fatal(ReaderContext.java:68) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
at org.springframework.beans.factory.parsing.ReaderContext.fatal(ReaderContext.java:55) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
at org.springframework.security.config.SecurityNamespaceHandler.reportUnsupportedNodeType(SecurityNamespaceHandler.java:144) ~[spring-security-config-4.1.2.RELEASE.jar:4.1.2.RELEASE]
I am using Spring Security 4.1.2, and 4.3.1 for master Spring.
It is also unclear from Spring documentation whether sec:websocket-message-broker and sec:http should be used in conjunction for the web socket endpoint or are mutually exclusive.
Thanks for advice.
Sergey
P.S. My spring-security.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:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2
http://www.springframework.org/schema/security/spring-security-oauth2-1.0.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">
<sec:http pattern="/Consumer.svc/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager"
authentication-manager-ref="authenticationManager"
use-expressions="true">
<sec:anonymous enabled="false" />
<sec:intercept-url pattern="/Consumer.svc/**" access="isAuthenticated()" />
<sec:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
</sec:http>
<sec:http pattern="/WebSocket.svc" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager"
authentication-manager-ref="authenticationManager"
use-expressions="true">
<sec:anonymous enabled="false" />
<sec:intercept-url pattern="/WebSocket.svc" access="isAuthenticated()" />
<sec:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
</sec:http>
<sec:websocket-message-broker>
<sec:intercept-message pattern="/WebSocket.svc" access="isAuthenticated()" />
</sec:websocket-message-broker>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
</bean>
<bean id="oauthWebExpressionHandler"
class="org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler">
</bean>
<bean id="accessDecisionManager"
class="org.springframework.security.access.vote.UnanimousBased">
<constructor-arg>
<list>
<bean class="org.springframework.security.web.access.expression.WebExpressionVoter">
<property name="expressionHandler" ref="oauthWebExpressionHandler" />
</bean>
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</list>
</constructor-arg>
</bean>
<sec:authentication-manager alias="authenticationManager"/>
<oauth:resource-server id="resourceServerFilter"
resource-id="springsec" token-services-ref="offlineTokenServices" />
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<!-- ... also some other elements here ... -->
</beans>
It was necessary to add the following to pom.xml:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-messaging</artifactId>
<version>4.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>
And this to spring-security.xml:
<bean id="springSecurityMessagePathMatcher"
class="org.springframework.util.AntPathMatcher"/>
Now Spring does not throw an exception at startup and parses spring-security.xml fine, but it does not work either. SecurityContextHolder.getContext().getAuthentication() still returns null.
Related
I have this 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"
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/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 ">
<http pattern="/api/swagger-ui.html" security="none" xmlns="http://www.springframework.org/schema/security"/>
<http pattern="/api/webjars/**" security="none" xmlns="http://www.springframework.org/schema/security"/>
<http pattern="/api/swagger-resources/**" security="none" xmlns="http://www.springframework.org/schema/security"/>
<http pattern="/api/v2/api-docs" security="none" xmlns="http://www.springframework.org/schema/security"/>
<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="IS_AUTHENTICATED_FULLY"/>
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER"/>
<access-denied-handler ref="oauthAccessDeniedHandler"/>
</http>
<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"/>
</list>
</constructor-arg>
</bean>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="sample"/>
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"/>
<oauth:resource-server id="resourceServerFilter" resource-id="sample" token-services-ref="remoteTokenServices"/>
<bean id="remoteTokenServices" class="org.springframework.security.oauth2.provider.token.RemoteTokenServices">
<property name="checkTokenEndpointUrl" value="${oauth.check.token.url}"/>
<property name="clientId" value="${oauth.client:crdb}"/>
<property name="clientSecret" value="${oauth.secret:secret}"/>
</bean>
<authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security">
</authentication-manager>
<oauth:expression-handler id="oauthExpressionHandler"/>
<oauth:web-expression-handler id="oauthWebExpressionHandler"/>
</beans>
Fortify returns to me Spring security misconfiguration: incorrect request matcher type on line 9, 10, 11, 15. Can someone give me a point how to solve this issue? It seems there is a some path problem, but Im not so familiar with fortify, so I dont know how to solve this issue.
it seems like you have problem using <http/> tag used for configuration. Look closely whether you are using valid attributes related to that tag. You can simply identify the available properties/attributes for that by clicking on the tag.
It seems like xmlns="http://www.springframework.org/schema/security" this is making error because <http> does not have xmlns property.
You also don't need to define it in every http.
Try removing xmlns property from <http> tag and it should work.
For Reference: Spring Security XML Configuration
Available <http> attributes for configuration:
<http pattern=""
name=""
access-decision-manager-ref=""
authentication-manager-ref=""
auto-config=""
create-session=""
disable-url-rewriting=""
entry-point-ref=""
jaas-api-provision=""
once-per-request=""
realm=""
request-matcher=""
request-matcher-ref=""
security=""
security-context-repository-ref=""
servlet-api-provision=""
use-expressions=""/>
I am new to Spring Security OAuth2 using version 2.0.10.RELEASE implementation. I developed code using 'InMemoryTokenStore' and I'm impressed with the way it works (it creates access_token, 'refresh_token' etc..), but I don't have enough understanding on how it works yet. Can anyone please help to know / provide understanding on how it works?
Is 'InMemoryTokenStore' the safest implementation from hacking perspective? I also see there are many implementation provided by OAuth2 like JdbcTokenStore, JwtTokenStore,KeyStoreKeyFactory. I don't think storing access_token into the database in the great idea like JdbcTokenStore does.
Which Implementation we should follow and why ?
spring-security-oauth2.xml file
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns: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.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/beans http://www.springframework.org/schema/beans/spring-beans.xsd ">
<http pattern="/oauth/token" auto-config="true" use-expressions="true" create-session="stateless" authentication-manager-ref="authenticationManager"
xmlns="http://www.springframework.org/schema/security" >
<!-- <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" /> -->
<intercept-url pattern="/oauth/token" access="permitAll" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<!-- Added this to fix error -->
<sec:csrf disabled="true" />
</http>
<http pattern="/resources/**" auto-config="true" use-expressions="true" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/resources/**" method="GET" />
<!-- <intercept-url pattern="/resources/**" access="IS_AUTHENTICATED_FULLY" /> -->
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<!-- Added this to fix error -->
<sec:csrf disabled="true" />
</http>
<http pattern="/logout" create-session="never" auto-config="true" use-expressions="true"
entry-point-ref="oauthAuthenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/logout" method="GET" />
<sec:logout invalidate-session="true" logout-url="/logout" success-handler-ref="logoutSuccessHandler" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<!-- Added this to fix error -->
<sec:csrf disabled="true" />
</http>
<bean id="logoutSuccessHandler" class="demo.oauth2.authentication.security.LogoutImpl" >
<property name="tokenstore" ref="tokenStore"></property>
</bean>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="springsec/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
</bean>
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="clientDetails" class="demo.oauth2.authentication.security.ClientDetailsServiceImpl"/>
<authentication-manager id="userAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider ref="customUserAuthenticationProvider">
</authentication-provider>
</authentication-manager>
<bean id="customUserAuthenticationProvider"
class="demo.oauth2.authentication.security.CustomUserAuthenticationProvider">
</bean>
<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="userAuthenticationManager"/>
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
resource-id="springsec" token-services-ref="tokenServices" />
<!-- <bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" /> -->
<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="300000"></property>
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<mvc:annotation-driven /> <!-- Declares explicit support for annotation-driven MVC controllers #RequestMapping, #Controller -->
<mvc:default-servlet-handler />
<bean id="MyResource" class="demo.oauth2.authentication.resources.MyResource"></bean>
</beans>
You're mixing in several things together. InMemoryTokenStore, JwtTokenStore and JdbcTokenStore are only supposed to be used for different cases. There is no such a thing which of them is safer and which is not.
JwtTokenStore
JwtTokenStore encodes token-related data into the token itself. It does not make tokens persistent and requires JwtAccessTokenConverter as a translator between a JWT-encoded token
and OAuth authentication information. ("Spring Essentials" by Shameer Kunjumohamed, Hamidreza Sattari).
The important thing is that tokens are not persisted at all and validated "on the fly" based on signature.
One disadvantage is that you can't easily revoke an access token, so they normally are granted with short expiry and the revocation is handled at the refresh token. Another disadvantage is that the tokens can get quite large if you are storing a lot of user credential information in them. The JwtTokenStore is not really a "store" in the sense that it doesn't persist any data. read more
InMemoryTokenStore
InMemoryTokenStore stores tokens in server memory so it's hardly possible to share them among different servers. You'll lose all access tokens in InMemoryTokenStore when you restart your authorisation server. I'd prefer to use InMemoryTokenStore only during development and not in a production environment.
The default InMemoryTokenStore is perfectly fine for a single server (i.e. low traffic and no hot swap to a backup server in the case of failure). Most projects can start here, and maybe operate this way in development mode, to make it easy to start a server with no dependencies. read more
JdbcTokenStore
The JdbcTokenStore is the JDBC version of the same thing, which stores token data in a relational database. Use the JDBC version if you can share a database between servers, either scaled up instances of the same server if there is only one, or the Authorization and Resources Servers if there are multiple components. To use the JdbcTokenStore you need "spring-jdbc" on the classpath. read more
In case of JdbcTokenStore you're saving the tokens in real database. So you're safe in case of Authorization service restart. The tokens can be also easily shared among the servers and revoked. But you have more dependancies for database.
I'm using jersey as a RESTFul webserver. (jersey-server 1.8) with spring (3.2.0.RELEASE) and hibernate.
My endpoints are protected using spring-security (3.1.3.RELEASE) with 2 legged oAuth 1.0a (spring-security-oauth 1.0.0.M4 )
Everything works as expected and the securing works.
Inside my ConsumerDetailsServiceImpl (implements ConsumerDetailsService, UserDetailsService, AuthenticationProvider) i throw different exceptions (all are of form OAuthException now, but i want to add my own custom exceptions)
However no matter what i tried i cannot get to customize the different authentication and access denied exceptions the way i want, i always get the default 401 page
My API is agreed to always return a json responseobject so i need to catch these exceptions and show 401 pages with json inside it
My securty.xml
<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" xmlns:oauth="http://www.springframework.org/schema/security/oauth"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/security/oauth
http://www.springframework.org/schema/security/spring-security-oauth.xsd">
<!-- Authentication beans -->
<bean name="consumerDetailsService" class="com.securitytest.core.services.impl.ConsumerDetailsServiceImpl" />
<bean name="oauthProcessingFilterEntryPoint" class="org.springframework.security.oauth.provider.OAuthProcessingFilterEntryPoint" />
<bean id="oAuthAuthenticationHandler" class="com.securitytest.core.security.CustomOAuthAuthenticationHandler" />
<security:http auto-config="true" use-expressions="true" entry-point-ref="oauthProcessingFilterEntryPoint" >
<security:intercept-url pattern="/rest/secured/**" access="isAuthenticated()" />
<security:intercept-url pattern="/rest/unsecured/**" access="permitAll" />
<security:intercept-url pattern="/rest/**" access="isAuthenticated()" />
<security:form-login login-page='/login' default-target-url="/home" authentication-failure-handler-ref="authenticationFailureHandler"/>
<security:access-denied-handler ref="accessDeniedHandler" />
</security:http>
<bean id="accessDeniedHandler" class="com.securitytest.core.security.CustomoauthAccessDeniedHandler" />
<!-- this was just a test, it didn't work obviously -->
<bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
<property name="exceptionMappings">
<props>
<prop key="org.springframework.security.authentication.BadCredentialsException">/login/badCredentials</prop>
<prop key="org.springframework.security.authentication.CredentialsExpiredException">/login/credentialsExpired</prop>
<prop key="org.springframework.security.authentication.LockedException">/login/accountLocked</prop>
<prop key="org.springframework.security.authentication.DisabledException">/login/accountDisabled</prop>
</props>
</property>
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="consumerDetailsService" />
</security:authentication-manager>
<bean id="nonceServices" class="org.springframework.security.oauth.provider.nonce.InMemoryNonceServices" />
<oauth:provider
auth-handler-ref="oAuthAuthenticationHandler"
consumer-details-service-ref="consumerDetailsService"
nonce-services-ref="nonceServices"
token-services-ref="tokenServices"
require10a="true"
/>
<oauth:token-services id="tokenServices" />
Stuff i tried
Change the exceptionTranslationFilter -> is not allowed by the docs
Add a custom access-denied-handler and a authentication-failure-handler-ref
<security:http auto-config="true" use-expressions="true" entry-point-ref="oauthProcessingFilterEntryPoint" >
<security:intercept-url pattern="/rest/secured/**" access="isAuthenticated()" />
<security:intercept-url pattern="/rest/unsecured/**" access="permitAll" />
<security:intercept-url pattern="/rest/**" access="isAuthenticated()" />
<security:form-login login-page='/login' default-target-url="/home" authentication-failure-handler-ref="authenticationFailureHandler"/>
<security:access-denied-handler ref="accessDeniedHandler" />
</security:http>
-> this gets blatantly ignored by spring-security/oauth
Add a custom filter after the EXCEPTION_TRANSLATION_FILTER
<security:custom-filter after="EXCEPTION_TRANSLATION_FILTER" ref="myFilter" />
MyFilter just implements "javax.servlet.Filter".
-> It goes into the doFilter but i have no idea what do with it (i can't see which exception is thrown, if any).
Any help is appreciated!!
I am quite late answering this question and you might have resolved or moved to some other alternative. However I recently dived into the Oauth and faced similar problem and managed to resolve it. Sharing it as reference for others.
I have used Oauth's MediaTypeAwareAccessDeniedHandler and MediaTypeAwareAuthenticationEntryPoint for error handling. As per documentation, it defaults to 401 error page. However, from source code, error response content type is dependent upon request Accept-Type. But requesting clients to always sent Accept-Type as application/json is like asking fox to safeguard hen.
Good news is that response type support setter injection. So simple solution was to override defaults and inject response property to always sent JSON response irrespective of Accept-Type
<bean id="accessDeniedHandler" class="org.springframework.security.oauth2.provider.error.MediaTypeAwareAccessDeniedHandle"/>
<property name="responses">
<map>
<entry key="*/*" value="{error:"%s"}"></entry>
</map>
</property>
</bean>
I try to implement my own example based on official tutorial Sparklr2/Tonr2. Everything looks good but when I remove from web.xml in my Tonr2 implementation, spring security filter I have exception:
No redirect URI has been established for the current request
I can't understand what URL should I use. Here is my code, for client implementation:
<!--apply the oauth client context -->
<oauth:client id="oauth2ClientFilter" />
<!--define an oauth 2 resource for sparklr -->
<oauth:resource id="provider" type="authorization_code" client-id="client" client-secret="secret"
access-token-uri="http://localhost:8080/provider/oauth/token" user-authorization-uri="http://localhost:8080/provider/oauth/authorize" scope="read,write" />
<beans:bean id="clientController" class="com.aouth.client.ClientController">
<beans:property name="trustedClientRestTemplate">
<oauth:rest-template resource="provider" />
</beans:property>
</beans:bean>
And for provider:
<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 />
</http>
<authentication-manager id="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<!-- The OAuth2 protected resources are separated out into their own block so we can deal with authorization and error handling
separately. This isn't mandatory, but it makes it easier to control the behaviour. -->
<http pattern="/secured" create-session="never" access-decision-manager-ref="accessDecisionManager" xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/secured" access="ROLE_USER,SCOPE_READ" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<http-basic />
</http>
<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>
<oauth:resource-server id="resourceServerFilter" resource-id="resource" token-services-ref="tokenServices" />
<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="clientDetailsService" ref="clientDetails"/>
</bean>
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" />
<http auto-config="true" xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/test" access="ROLE_USER" />
<intercept-url pattern="/" access="IS_AUTHENTICATED_ANONYMOUSLY" />
</http>
<authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security">
<authentication-provider>
<user-service>
<user name="pr" password="pr" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</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 />
</oauth:authorization-server>
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="client" resource-ids="resource" authorized-grant-types="authorization_code, implicit"
authorities="ROLE_CLIENT" scope="read,write" secret="secret" />
</oauth:client-details-service>
I just want my client to work without spring security. And when I need my protected resource I want to login only on provider side.
You 2nd XML that you pasted here is the spring's XML for the oauth-provider and the protected-resource, which in your case run in the same webapp. (you can separate them, of course, if you wish).
The client (the 1st pasted-XML) is a different story. If I understand you correctly, you want your client to run without Spring's help (to be a regular webapp, and not spring-security-oauth-client webapp).
You have to understand how oAuth works: the client tries to get to a protected resource; if it does not have the access-token, it is being redirected to the oAuth-provider (that shows the login page and supplies the token). By the standard, the request for the access-token MUST contain a "redirect-uri" param, so after a successful login, the oAuth-provider knows where to redirect the client to. The oAuth client does it for you, and if you delete the "oauth client" from your web.xml, you now have to implement this by yourself.
Thanks for your answer. But I still don't understand how spring
security influences my oAuth client. And can I use for client side
spring-oauth (spring-mvc) without spring-security?
When you write this line in your XML:
< oauth:client id="oauth2ClientFilter" />
it means that you use spring-security-oauth, which is a package dedicated for oauth, built on spring-security. If you dig in, it puts a special filter (OAuth2ClientContextFilter) in the chain that handles the oAuth stuff, that are relevant for the client. One of them is sending the request with all the params ("redirect-uri" is one of them).
If you decide NOT to use spring-security-oauth, well - you will have to implement this logic by yourself...
Hope that helps!
I am attempting to authenticate via X.509 smart card to my application. For the moment, my application doesn't have any users defined, so I'm trying to use anonymous authentication. I'll switch it to hasRole() once I create users.
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="myUserService" />
</security:authentication-manager>
<!-- TODO: Enable this once I am ready to start annotating the service interfaces -->
<security:global-method-security pre-post-annotations="enabled" />
<security:http use-expressions="true" authentication-manager-ref="authenticationManager" access-denied-page="/index2.xhtml" >
<security:anonymous enabled="true" />
<security:x509 subject-principal-regex="CN=(.*?)," user-service-ref="myUserService" />
<security:intercept-url pattern="/**" access="isAnonymous()" requires-channel="https" />
<!-- TODO: configure invalid-session-url, delete sessionid -->
<security:session-management>
<security:concurrency-control max-sessions="2" error-if-maximum-exceeded="true"/>
</security:session-management>
</security:http>
<bean id="roleVoter"
class="org.springframework.security.access.vote.RoleHierarchyVoter">
<constructor-arg ref="roleHierarchy" />
</bean>
<bean id="roleHierarchy"
class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
<property name="hierarchy">
<value>
ROLE_USER > ROLE_AUTHENTICATED
ROLE_AUTHENTICATED > ROLE_UNAUTHENTICATED
ROLE_UNAUTHENTICATED > ROLE_ANONYMOUS
</value>
</property>
</bean>
It seems to be caught in the infinite loop issue, which I thought I was avoiding using isAnonymous().
I'm probably making a dumb error, so if someone can point out said stupidity, I'd be grateful.
The issue was a problem with configuring FacesServlet in web.xml. The FacesServlet was mapped to one path, which seemed to be incompatible with the intercept-url defined for Spring Security.
We've since jettisoned JSF (and good riddance).