Pramod Karandikar
Pramod Karandikar

Reputation: 5329

Spring-OAUTH2.0: No resource available error on calling /oauth/token

We have a set of ReST webservices which we need to protect using OAUTH2.0. I am trying to implement OAUTH2.0 by referring to the below resources:

However, after doing the required configuration, I am trying to hit the URL
http://localhost:8080/{project-name}/oauth/token?grant_type=password&client_id=client1&client_secret=client1&username=admin&password=admin

Tomcat throws error that - The requested resource is not available.

When I tried to place a debug point inside ClientDetailsServiceImpl.java, the flow came there with the correct details. Not able to understand what I am doing wrong here. Any suggestions are appreciated. TIA.

Below are the file details:
Spring Configuration 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-1.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.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-3.2.xsd ">


    <http pattern="/oauth/token" create-session="stateless"
        authentication-manager-ref="authenticationManager"
        xmlns="http://www.springframework.org/schema/security" > 
        <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
        <anonymous enabled="false" />
        <http-basic entry-point-ref="clientAuthenticationEntryPoint" />
        <custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" /> 
        <access-denied-handler ref="oauthAccessDeniedHandler" />
    </http>

    <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" access="IS_AUTHENTICATED_FULLY" />
        <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="in.test.server.security.oauth.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="in.test.server.security.oauth.ClientDetailsServiceImpl"/>

    <authentication-manager id="userAuthenticationManager" 
        xmlns="http://www.springframework.org/schema/security">
        <authentication-provider  ref="customUserAuthenticationProvider">
        </authentication-provider>
    </authentication-manager>

    <bean id="customUserAuthenticationProvider"
        class="in.test.server.security.oauth.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="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="in.test.server.resource.CommonResource"></bean>

</beans>

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"
    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>in-test-gcp-server</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:applicationContext.xml
            classpath:security-config.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>

    <servlet>
        <servlet-name>jersey-serlvet</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>in.test.server.resource.TestRSApplication</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>


    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>CorsFilter</filter-name>
        <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CorsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- Added for 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>
</web-app>

ClientDetailsServiceImpl.java

package in.test.server.security.oauth;

import java.util.ArrayList;
import java.util.List;

import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.BaseClientDetails;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.NoSuchClientException;
import org.springframework.stereotype.Service;

@Service
public class ClientDetailsServiceImpl implements ClientDetailsService {

    public ClientDetails loadClientByClientId(String clientId)
            throws OAuth2Exception {
if (clientId.equals("client1")) {

            List<String> authorizedGrantTypes=new ArrayList();
            authorizedGrantTypes.add("password");
            authorizedGrantTypes.add("refresh_token");
            authorizedGrantTypes.add("client_credentials");

            BaseClientDetails clientDetails = new BaseClientDetails();
            clientDetails.setClientId("client1");
            clientDetails.setClientSecret("client1");
            clientDetails.setAuthorizedGrantTypes(authorizedGrantTypes);

            return clientDetails;

        } else if(clientId.equals("client2")){

            List<String> authorizedGrantTypes=new ArrayList();
            authorizedGrantTypes.add("password");
            authorizedGrantTypes.add("refresh_token");
            authorizedGrantTypes.add("client_credentials");


            BaseClientDetails clientDetails = new BaseClientDetails();
            clientDetails.setClientId("client2");
            clientDetails.setClientSecret("client2");
            clientDetails.setAuthorizedGrantTypes(authorizedGrantTypes);

            return clientDetails;
        }


        else{
            throw new NoSuchClientException("No client with requested id: "
                    + clientId);
        }
    }




}

CustomUserAuthenticationProvider.java

package in.test.server.security.oauth;

import java.util.ArrayList;
import java.util.List;

import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;

public class CustomUserAuthenticationProvider implements AuthenticationProvider{

    public Authentication authenticate(Authentication authentication)
            throws AuthenticationException {
        if(authentication.getPrincipal().equals("user")&& authentication.getCredentials().equals("user"))
        {

            List<GrantedAuthority> grantedAuthorities = new ArrayList();
            UsernamePasswordAuthenticationToken auth=new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(),grantedAuthorities);


            return auth;

        }
        else if(authentication.getPrincipal().equals("admin")&& authentication.getCredentials().equals("admin"))
        {
            List<GrantedAuthority> grantedAuthorities = new ArrayList();
            UsernamePasswordAuthenticationToken auth=new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(),grantedAuthorities);

            return auth;
        }
        else if(authentication.getPrincipal().equals("user1")&& authentication.getCredentials().equals("user1"))
        {
            List<GrantedAuthority> grantedAuthorities = new ArrayList();
            UsernamePasswordAuthenticationToken auth=new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(),grantedAuthorities);

            return auth;
        }
        else{
                throw new BadCredentialsException("Bad User Credentials.");
        }
    }

    public boolean supports(Class<?> arg0) {
        // TODO Auto-generated method stub
        return true;
    }






}

Upvotes: 1

Views: 2011

Answers (1)

dmoore62
dmoore62

Reputation: 46

In your web.xml you need a servlet-mapping tag with a url-pattern attribute that points to /oauth/token

Something like:

<servlet-mapping>
    <servlet-name>spring <!-- Or whatever your dispatch servlet is called --></servlet-name>
    <url-pattern>/oauth/token</url-pattern>
</servlet-mapping>

Upvotes: 3

Related Questions