Alex Man
Alex Man

Reputation: 4886

RestController not working in oauth2 Spring Boot

I have setup a auth server and resource server as mentioned in the below article http://www.hascode.com/2016/03/setting-up-an-oauth2-authorization-server-and-resource-provider-with-spring-boot/

I downloaded the code and it is working fine. Now the issue is that in the resource provider project there is only one RestController annotated class as shown below

package com.hascode.tutorial;

import java.util.UUID;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Scope;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
@EnableResourceServer
public class SampleResourceApplication {
    public static void main(String[] args) {
        SpringApplication.run(SampleResourceApplication.class, args);
    }

    @RequestMapping("/")
    public String securedCall() {
        return "success (id: " + UUID.randomUUID().toString().toUpperCase() + ")";
    }
}

Now when I create a different class annotated with @RestController as shown below

@RestController
@RequestMapping("/public")
public class PersonController {

    @Autowired
    private PersonRepository personRepo;

    @RequestMapping(value = "/person", method = RequestMethod.GET)
    public ResponseEntity<Collection<Person>> getPeople() {
        return new ResponseEntity<>(personRepo.findAll(), HttpStatus.OK);
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public ResponseEntity<Person> getPerson(@PathVariable long id) {
        Person person = personRepo.findOne(id);

        if (person != null) {
            return new ResponseEntity<>(personRepo.findOne(id), HttpStatus.OK);
        } else {
            return new ResponseEntity<>(null, HttpStatus.NOT_FOUND);
        }
    }

    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity<?> addPerson(@RequestBody Person person) {
        return new ResponseEntity<>(personRepo.save(person), HttpStatus.CREATED);
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public ResponseEntity<Void> deletePerson(@PathVariable long id, Principal principal) {
        Person currentPerson = personRepo.findByUsername(principal.getName());

        if (currentPerson.getId() == id) {
            personRepo.delete(id);
            return new ResponseEntity<Void>(HttpStatus.OK);
        } else {
            return new ResponseEntity<Void>(HttpStatus.UNAUTHORIZED);
        }
    }

    @RequestMapping(value = "/{id}/parties", method = RequestMethod.GET)
    public ResponseEntity<Collection<Party>> getPersonParties(@PathVariable long id) {
        Person person = personRepo.findOne(id);

        if (person != null) {
            return new ResponseEntity<>(person.getParties(), HttpStatus.OK);
        } else {
            return new ResponseEntity<>(null, HttpStatus.NOT_FOUND);
        }
    }

}

but when I tried to access the service (http://localhost:9001/resources/public/person) I am getting 404

{
    "timestamp": 1508752923085,
    "status": 404,
    "error": "Not Found",
    "message": "No message available",
    "path": "/resources/public/person"
}

when I access http://localhost:9001/resources/ I am getting the correct result like

success (id: 27DCEF5E-AF11-4355-88C5-150F804563D0)

Should I register the Contoller anywherer or am I missing any configuration

https://bitbucket.org/hascode/spring-oauth2-example

UPDATE 1

ResourceServerConfiguration.java

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration  extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
        .anonymous().and()
        .authorizeRequests()
        .antMatchers("/resources/public/**").permitAll()
        .antMatchers("/resources/private/**").authenticated();
    }
}

OAuth2SecurityConfiguration.java

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
        .anonymous().and()
        .authorizeRequests()
        .antMatchers("/resources/public/**").permitAll()
        .antMatchers("/resources/private/**").authenticated();
    }
}

UPDATE 2

@Override
    public void configure(HttpSecurity http) throws Exception {
         http.authorizeRequests()
         .antMatchers("/resources/public/**").permitAll() //Allow register url
         .anyRequest().authenticated().and()
         .antMatcher("/resources/**").authorizeRequests() //Authenticate all urls with this body /api/home, /api/gallery
         .antMatchers("/resources/**").hasRole("ADMIN")
         .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); //This is optional if you want to handle exception
    }

Upvotes: 2

Views: 3465

Answers (2)

Make your new controller PersonController discoverable by Spring Boot either by using @ComponentScan on a configuration class or by moving PersonController to a package in or under your main class annotated with @SpringBootApplication.

Second fix your OAuth2SecurityConfiguration class like so

@Configuration
@EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .anonymous().disable()
            .authorizeRequests()
            .antMatchers("/oauth/token").permitAll(); //This will permit the (oauth/token) url for getting access token from the oauthserver.
    }        

}

Now fix your resource server like so

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration  extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/api/v1/register", "/api/v1/publicOne", "/api/v1/publicTwo").permitAll() //Allow urls
            .anyRequest().authenticated().and()
            .antMatcher("/api/**").authorizeRequests() //Authenticate all urls with this body /api/home, /api/gallery
            .antMatchers("/api/**").hasRole("ADMIN")
            .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); //This is optional if you want to handle exception
    }
}

Find the complete source code here. Hope this helps.

Note: You can customize your urls based on the above answer.

Upvotes: 3

Zenith
Zenith

Reputation: 1207

Why your request url is http://localhost:9001/resources/public/person

I think it should be like http://localhost:9001/public/person

Upvotes: 1

Related Questions