Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring OAuth: Resource Server with Authorization Server backend

I want to develop two independent services, one for the business stuff and one for the user authentication using Spring OAuth 2

Let's call them Business-Service and OAuth-Service.

Now I want the Business-Service delegate to the OAuth-Service if a request is not authenticated. The client application (an Android app) should not know about the OAuth-Service a priori, it should only be delegated to it by the Business-Service with an 302 HTTP redirect for non-authenticated request. To be precise, I want my API landing page to provide a link to http://businessservice.com/login and when my client app decides to follow this link, it gets redirected to the OAuth-Service.

If I annotate the Business-Service with @EnableOAuth2Resource , all of its resources are protected returning a 401 when I curl them without an access token. So far so good. If I provide an access token like this:

curl -v http://localhost:8667/resource/ -H "Authorization: Bearer $TOKEN"

I can access the resource. Still good.

However if I annotate the Business-Service with @EnableOAuth2Sso for enabling the redirection to the OAuth service, it looses the capability of accessing the resources with an access token (same curl as above), it only returns a 302 to the login page http://localhost:8667/login

If I use both annotations, the @EnableOAuth2Resource always seems to "win", as the authentication works but calling http://localhost:8667/login returns a 404.

So what is the right way to create a resource server that delegates to the auth server for non-authenticated calls?

like image 588
krinklesaurus Avatar asked Mar 12 '15 15:03

krinklesaurus


1 Answers

After trying around for hours I now found a solution.

The Business Server (Resource Server) now looks as follows:

@SpringBootApplication
@EnableOAuth2Sso
@EnableOAuth2Resource
public class BusinessService {

    public static void main(final String[] args) {
        final ConfigurableApplicationContext context = SpringApplication.run(BusinessService.class, args);
    }

}

with two configurations, one for the SSO:

@Configuration
public class OAuth2SsoConfiguration extends OAuth2SsoConfigurerAdapter {

    @Override
    public void match(final RequestMatchers matchers) {
        matchers.antMatchers("/");
    }

    @Override
    public void configure(final HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().permitAll();
    }

}

and one for the Resource:

@Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(final HttpSecurity http) throws Exception {
        http.requestMatchers().antMatchers("/resource/**").and().authorizeRequests().anyRequest().authenticated().antMatchers("/").permitAll();

    }

}



This results in the following:

curl -v http://localhost:8667/

returns

HTTP/1.1 200 OK
{"links":[{"rel":"login","href":"http://localhost:8667/login"}]}



curl -v http://localhost:8667/resource/

returns

HTTP/1.1 401 Unauthorized
{"error":"unauthorized","error_description":"Full authentication is required to access this resource"}



curl -v http://localhost:8667/login

returns

HTTP/1.1 302 Found
Location: http://localhost:8666/user/oauth/authorize?client_id=clientId&redirect_uri=http%3A%2F%2Flocalhost%3A8667%2Flogin&response_type=code&state=YmmNO9

So my business servie is secured with as a resource server returning a 401 for all business resources. The root of the service is applicable for all clients so they can discover the login relation and if they follow this relation, they're redirected to the Authorization server

like image 128
krinklesaurus Avatar answered Oct 18 '22 05:10

krinklesaurus