Spring: Securing REST API with BasicAuth

23 07 2016

The simpliest, yet effective way to secure Spring REST API is to use Basic Auth. I’m going to show how to do it with Spring Security.

Note

Basic Auth is stateless (no need to manage sessions) and simple to implement. However it should be used with https only if outside of a trusted network. Also be aware that there are issues with Basic Auth (http://security.stackexchange.com/questions/988/is-basic-auth-secure-if-done-over-https)

Source Code

As usual, get it from my GitHub: https://github.com/yacekmm/looksok/tree/HttpBasicAuthDemo/Spring/SecurityBasicAuth

1. Create a project

Use your favorite tool. I choose Spring Boot Initializr in IntelliJ. Add web and security starter poms:

Przechwytywanie

Note that right after you add the security starter pom to your classpath, the auto configuration kicks in and your app is secured by default (the default password is logged on the application startup). I will override that default configuration and customize it later on.

2. Create Controller with urls to be secured

The most straight forward one as possible like mine below:

@RestController
@RequestMapping("/api")
public class SecuredController {

    @RequestMapping(value = "/secured", method = GET, produces = TEXT_PLAIN_VALUE)
    public String securedGet(){
        return "You have access to secured API!";
    }

    @RequestMapping(value = "/admin", method = GET, produces = TEXT_PLAIN_VALUE)
    public String adminGet(){
        return "Welcome, Admin";
    }

    @RequestMapping(value = "/open", method = GET, produces = TEXT_PLAIN_VALUE)
    public String openedGet(){ return "this API does not require authentication"; }
}

It contains 3 endpoints. Each of them I will secure to be accessible on various levels.

3. Create Basic Auth security configuration for selected endpoints

As in one of my previous tutorials (Spring Security Tutorial: Authorization and user roles), you need to extend the WebSecurityConfigurerAdapter:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    ...
}

and configure the HttpSecurity in there:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .httpBasic()
        .and()
            .authorizeRequests()
            .antMatchers("/api/secured").authenticated()
            .antMatchers("/api/admin").hasRole("ADMIN")
            .antMatchers("/api/open").permitAll()
            .anyRequest().authenticated();
}

What just happened here?

  • first of all with httpBasic() you say that BasicAuth will be in use
  • then you say that want to authorizeRequests() so that:
    • url matching “/api/secured” is accessible for all authenticated users
    • url matching “/api/admin” is accessible for ADMIN users only
    • url matching “/api/open” is accessible with no authentication required
    • any other request is accessible for all authenticated() users

4. Create security configuration: usernames and passwords

Here I create two user accounts with USER and ADMIN role. That method is also in my WebsecurityConfig class. Using those accounts you can log in to the application:

@Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
            .withUser("admin").password("superhard").roles("ADMIN")
        .and()
            .withUser("user").password("easyone").roles("USER");
}

Normaly you would use the AuthenticationProvider, probably connected with your database or LDAP. This is separate big subject not to be cevered in this article.

5. Go ahead and try it!

Run the app and:

  1. head over to url 127.0.0.1:8080/api/open – you should access it without logging in
  2. head over http://127.0.0.1:8080/api/secured – the browser will ask you for username and password: type ‘user’ and ‘easyone’. Then you should access the site
  3. head over to url http://127.0.0.1:8080/api/admin – you will get 403 Forbidden, since browser cached your auth data and reused it. Only admin is permitted to access that url.
  4. To log in as another user you need to restart your browser and open the url once again. You can also use private browsing.
Advertisements




Microservice architecture discussion

23 08 2014

Microservice architecture is a quite new concept which currently I am fond of. I am gaining more and more experience and practical knowledge about its strengts and weaknesses as well. Until the system is deployed, still new conclusions appear.

And new articles appear on the web. I would like to share an article that is a proof that not everyone sees microservices the same way. There are of course new challenges in such design, totally different than in plain old monolyth apps, and of course big advantages. Thiere is a trade off – What is better.

Here is an article, woth reading to know other’s opinion on topic: http://contino.co.uk/microservices-not-a-free-lunch/

 

Surely not everything should be done as microservice, not everything fits, but I am afraid that authors’ doubts make him think that monolythic is not that bad. I mean, Iagree with arguments that API design is a challenge, however good API is crucial for an app, for a class and for system! this makes system responsibilities well defined, clear and testable.

So mostly I agree with author that these are challenges, however in my opinion microservices requires a good, well defined design from developers. Implementing a good design is challenging and not easy. Good software development is not a free lunch, neither are microservices. So I do not agree that things described in article are something new for developers. We all follow good designds. Aren’t we…?








%d bloggers like this: