Lokesh Paunikar
Lokesh Paunikar

Reputation: 1709

oauth2 spring security over RESTEasy API's

I am trying to secure my rest services by Oauth 2.0 spring security. I google for the same and got some example on it. I tried one example with the help of google and able to generate access_token. But when I am going to access my protected resource it becomes accessible without passing any access_token, instead it should show some authorization error message. What I am missing here???

URL to receive authorization code:

http://localhost:8080/springsecurity-oauth2-POC/oauth/token?grant_type=password&client_id=my-trusted-client-with-secret&client_secret=somesecret&username=marissa&password=koala 

got the token like,
{"access_token":"64ee1cf7-2445-40d8-86a5-c4900b47db9e","token_type":"bearer","refresh_token":"e7c7bce1-35db-4879-a2de-e6690f8d482d","expires_in":299969}

Resource URL

http://localhost:8080/springsecurity-oauth2-POC/resources/MyResource/getMyInfo

As it doesn't contain any token but still I am able to access it.

My spring-servlet.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-1.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd ">


    <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>

    <!-- 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="/resources/*" 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="/resources/*" access="ROLE_USER" />
        <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
        <access-denied-handler ref="oauthAccessDeniedHandler" />
    </http>

    <http pattern="/logout" create-session="never" 
        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" />
    </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="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>

    <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>

    <authentication-manager alias="authenticationManager"
        xmlns="http://www.springframework.org/schema/security">
        <!-- <authentication-provider user-service-ref="clientDetailsUserService" /> -->
        <authentication-provider>
            <user-service id="userDetailsService">
                <user name="marissa" password="koala" authorities="ROLE_USER" />
                <user name="paul" password="emu" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>

    <bean id="clientDetailsUserService"
        class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
        <constructor-arg ref="clientDetails" />
    </bean>

    <!-- Used for the persistenceof tokens (currently an in memory implementation) -->
    <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" />

    <!-- Used to create token and and every thing about them except for their persistence that is reposibility of TokenStore (Given here is a default implementation) -->
    <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>

    <bean id="userApprovalHandler" class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
        <property name="tokenServices" ref="tokenServices" />
    </bean>

    <!-- authorization-server aka AuthorizationServerTokenServices is an interface that defines everything necessary for token management -->
    <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" />
    <!-- ClientsDeailsService: Entry Point to clients database (given is in memory implementation) -->
    <oauth:client-details-service id="clientDetails">

    <oauth:client client-id="my-trusted-client" authorized-grant-types="password,authorization_code,refresh_token,implicit"
    authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" scope="read,write,trust" access-token-validity="60" />

    <oauth:client client-id="my-trusted-client-with-secret" authorized-grant-types="password,authorization_code,refresh_token,implicit"
    secret="somesecret" authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" />
    <oauth:client client-id="my-client-with-secret" authorized-grant-types="client_credentials" authorities="ROLE_CLIENT"
    scope="read" secret="secret" />

    <oauth:client client-id="my-less-trusted-client" authorized-grant-types="authorization_code,implicit"
    authorities="ROLE_CLIENT" />

    <oauth:client client-id="my-less-trusted-autoapprove-client" authorized-grant-types="implicit"
    authorities="ROLE_CLIENT" />

    <oauth:client client-id="my-client-with-registered-redirect" authorized-grant-types="authorization_code,client_credentials"
    authorities="ROLE_CLIENT" redirect-uri="http://anywhere?key=value" scope="read,trust" />

    <oauth:client client-id="my-untrusted-client-with-registered-redirect" authorized-grant-types="authorization_code"
    authorities="ROLE_CLIENT" redirect-uri="http://anywhere" scope="read" />

    <oauth:client client-id="tonr" resource-ids="test" authorized-grant-types="authorization_code,implicit"
    authorities="ROLE_CLIENT" scope="read,write" secret="secret" />

    <!--Self defined client-->
    <oauth:client client-id="the_client" authorized-grant-types="authorization_code,client_credentials"
    authorities="ROLE_USER" scope="read,write,trust" secret="secret" />

    </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" />

    <mvc:annotation-driven />   <!-- Declares explicit support for annotation-driven MVC controllers  @RequestMapping, @Controller -->

    <mvc:default-servlet-handler /> 
</beans>

My Web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>Spring Secure REST</display-name>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-servlet.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  </listener>
  <filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
      <param-name>contextAttribute</param-name>
      <param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <servlet>
    <servlet-name>RESTService</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>RESTService</servlet-name>
    <url-pattern>/resources/*</url-pattern>
  </servlet-mapping>
  <servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

My Resource class contains

package demo.oauth2.authentication.resources;

import javax.ws.rs.GET;
import javax.ws.rs.Path;


@Path("/MyResource")
public class MyResource {


    @GET
    @Path("/createInfo")
    public String createInfo(){
        return "\n\n\t!!!Protected Resource(createInfo) Accessed !!!! Returning from Myresource createInfo\n";

    }

    @GET
    @Path("/getMyInfo")
    public String getMyInfo(){

        return "\n\n\t Protected Resource(getMyInfo) Accessed !!!! Returning from Myresource getMyInfo\n";
    }


    @GET
    @Path("/updateInfo")
    public String updateMyInfo(){
        return "\n\n\t Protected Resource(updateInfo) Accessed !!!! Returning from Myresource updateInfo\n";

    }

}

Upvotes: 3

Views: 7757

Answers (2)

PAA
PAA

Reputation: 12005

I see you're using same code from http://www.e-zest.net/blog/rest-authentication-using-oauth-2-0-resource-owner-password-flow-protocol/ site. If yes, then you need to use following code also

<http pattern="/resources/**" 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" />
    </http>

I was also facing the same, issue until you don't add above xml configuration, I'm also using same code and it works for me!! I've perform testing and attached the screen shots for your reference. enter image description here

In this case, I'm not passing token value, and it gives me expected error enter image description here

Now, I'm passing value of "access_token" and it's giving me protected resources. enter image description here

Hope this will be help you..

Upvotes: 1

Michal Korecki
Michal Korecki

Reputation: 123

Try double asterisk in:

<http pattern="/resources/**"

instead of

<http pattern="/resources/*"

Hope it helps.

Upvotes: 2

Related Questions