Showing posts with label Spring security. Show all posts
Showing posts with label Spring security. Show all posts

Wednesday, May 27, 2020

Spring Security with REST API

Spring Security with REST API 

Objectives

Today I would like to dive into security topic in Spring boot application. I base on my previous post (https://java-architect.blogspot.com/2020/05/spring-boot-rest-api-with-jpa.html) with the sources. I'm going to change and add protection to the API. There are two important aspect:

  • Authentication - process of identifying the user who calls the API
  • Authorization -  process of checking user's permission to call resources

The Authentication process can base on plain text password, digest method, JWT (Java WEB Token), OAuth, SAML or other method to identify user. Besides previously mentioned methods, very often applications are protected by certificates.


The simplest way to authenticate 

So, due the topic, the simplest way to enable user authentication is to add the appropriate configuration.



























For simplification I defined users and roles in memory. Of course in production environment that data should be fetched form LDAP, Data Base or other identity server.. 


package com.main.artsci.configutarion;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
       @SuppressWarnings("deprecation")
       @Bean
       public UserDetailsService userDetailsService() {
              User.UserBuilder users = User.withDefaultPasswordEncoder();
              InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
              manager.createUser(users.username("user").password("user").roles("USER").build());
              manager.createUser(users.username("admin").password("admin").roles("USER", "ADMIN").build());
               return manager;
        }
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .userDetailsService(userDetailsService());
}
@Override
protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests()
.antMatchers(HttpMethod.GET, "/regions/complex/**").hasRole("ADMIN")
.anyRequest()
.authenticated()
.and().httpBasic();
}
}

In "userDetailsService()" method I defined all necessary users for this test case. In "configure()" method I enabled authentication for every request and all users can have access to all resources except resource defined by path "/regions/complex/" where access has only administrator.

In addition I created SecurityWebApplicationInitializer 

public class SecurityWebApplicationInitializer
   extends AbstractSecurityWebApplicationInitializer {
}

Let's see the pom's changes. I added security libraries:

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
     </dependency>
     <dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
      </dependency>
<dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-core</artifactId>  
</dependency>
<dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-openid</artifactId>  
</dependency>
<dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-ldap</artifactId>  
</dependency>

  
Finally it is necessary to checks is requested resources are protected in a proper way.  

Let's see the results after fetching resource available to everyone who pass true the authentication process.
curl --user user:user http://localhost:8080/regions
[{"regionId":1,"name":"Europe"},{"regionId":2,"name":"Americas"},{"regionId":3,"name":"Asia"},{"regionId":4,"name":"Middle East and Africa"}]
The results are exactly we expect to achieve. Next what does happen if we try to fetch protected data? 
curl --user user:user http://localhost:8080/regions/complex/1
{"timestamp":"2020-05-27T07:20:00.487+0000","status":403,"error":"Forbidden", "message":"Forbidden","path":"/regions/complex/1"} 

The error occurs. There is no permission. Let's change user to admin.

curl --user admin:admin http://localhost:8080/regions/complex/1
{"regionId":1,"name":"Europe","countries":[{"countryId":"BE","name":"Belgium"},{"countryId":"CH","name":"Switzerland"},{"countryId":"DE","name":"Germany"},{"countryId":"DK","name":"Denmark"},{"countryId":"FR","name":"France"},{"countryId":"IT","name":"Italy"},{"countryId":"NL","name":"Netherlands"},{"countryId":"UK","name":"United Kingdom"}]}
And everything is correct :)