2
votes

How do you setup a separate Spring OAuth2 ResourceServer only, that uses and 3rd party AuthorizationServer

All examples I see always implement the ResourceServer and AuthorizationServer in same application.

I don't want to implement the AuthorizationServer as someone else is going to provide this.

Have tried with no luck

@Configuration
   @EnableResourceServer
   public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter

And application.yml includes

security:
  oauth2:
    resource:
      userInfoUri: https://...../userinfo

Adding to my question some further details::

In my understanding - with OAuth there are 4 players:

  • resource owner: a person
  • resource server: server exposing a protected API (protected by the authentication server)
  • authentication server: the server that handles issuing access tokens to clients
  • client: an application (say website) accessing the resource server API's after resource owner have given consent

I have tried various tutorials, but all seem to implement their own Authorisation server

http://www.swisspush.org/security/2016/10/17/oauth2-in-depth-introduction-for-enterprises https://gigsterous.github.io/engineering/2017/03/01/spring-boot-4.html

or are examples of implementing the client player

My Question is: How do I implement just the Resource Server which secures my REST API, via a 3rd party authentication server, nothing more.

2
The way I understand this guide is that it is implementing the client that users an external authentication server. Were as I am asking how to protect my own API via an external authentication server. To add to my question:Melissa
There is no question - just statements. Show what you have and which problem you got.StanislavL
As far as I know,You need to implement TokenServices to use Remote Authorization endpoint and Tokenextractors as well.karthik

2 Answers

2
votes

I have work this out - all you need is:

@SpringBootApplication
@EnableResourceServer
public class ResourceServer {

    public static void main(String[] args) {
        SpringApplication.run(ResourceServer.class, args);
    }
}

With the application.yml as posted in the original question of:

security:
 oauth2:
   resource:
     userInfoUri: https://........userinfo
-1
votes

I've created two sample separate applications, one of them acting as oauth client, and another one acting as a resource server, and both of them are using an external authentication server (which is facebook in this example).

The scenario in the example is as follows, the user opens app1 (oauth client) and gets redirected to first page, and once he clicks login, he'll be redirected to facebook login, and after a successful login, he will get back to the first page. If he clicked on the first button, a call to an api within the same application will be made, and will appear beside message 1 label, and if he clicked on the second button, a call to an api within app2 (resource server) will be made, and the message will be displayed beside message 2 label.

If you checked the logs, you will find the api call going from app1 to app2 containing the access token in the request parameters. Logs for app1 calling app2

Please find the source code on the git repository here

This is the configuration for app1 (oauth client)

app1 web security config

@Configuration
@EnableOAuth2Sso
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.antMatcher("/**").authorizeRequests().antMatchers("/", "/login**", "/webjars/**", "/error**").permitAll()
            .anyRequest().authenticated().and().logout().logoutSuccessUrl("/").permitAll().and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
@Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("OPTIONS");
    config.addAllowedMethod("GET");
    config.addAllowedMethod("POST");
    config.addAllowedMethod("PUT");
    config.addAllowedMethod("DELETE");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}
}

app1 application properties

security:
  oauth2:
    client:
      clientId: <your client id>
      clientSecret: <your client secret>
      accessTokenUri: https://graph.facebook.com/oauth/access_token
      userAuthorizationUri: https://www.facebook.com/dialog/oauth?redirect_url=https://localhost:8443/
      tokenName: access_token
      authenticationScheme: query
      clientAuthenticationScheme: form
      registered-redirect-uri: https://localhost:8443/
      pre-established-redirect-uri: https://localhost:8443/
    resource:
      userInfoUri: https://graph.facebook.com/me
logging:
  level:
    org.springframework.security: DEBUG

This is the configuration for app2 (resource server)

app2 resource server config

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    String[] ignoredPaths = new String[] { "/error", "/login", "/doLogut", "/home", "/pageNotFound", "/css/**",
            "/js/**", "/fonts/**", "/img/**" };

    @Value("${security.oauth2.resource.user-info-uri}")
    private String userInfoUri;

    @Value("${security.oauth2.client.client-id}")
    private String clientId;

    @Override
    public void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests().antMatchers(ignoredPaths).permitAll().anyRequest().authenticated();
    }

    @Primary
    @Bean
    public UserInfoTokenServices tokenService() {
        final UserInfoTokenServices tokenService = new UserInfoTokenServices(userInfoUri, clientId);
        return tokenService;
    }
}

app2 application properties

security:
  oauth2:
    resource:
      userInfoUri: https://graph.facebook.com/me
    client:
      client-id: <your client id>
logging:
  level:
    org.springframework.security: DEBUG  

This is where app1 controller calls an api on app2 (hi2 api)

@RestController
@CrossOrigin(origins = "*", allowedHeaders = "*")
public class UserController {

    @Autowired
    OAuth2RestTemplate restTemplate;

    @RequestMapping("/user")
    public Principal user(Principal principal) {
        return principal;
    }

    @RequestMapping("/hi")
    public String hi(Principal principal) {
        return "Hi, " + principal.getName();
    }

    @RequestMapping("/hi2")
    public String hi2(Principal principal) {
        final String greeting = restTemplate.getForObject("http://127.0.0.1:8082/api/hello", String.class);

        System.out.println(greeting);
        return greeting;
    }
}