Rest Service with Spring Security

Rest Service with Spring Security, Oauth and Gradle

Security in apps or Web services is very important, dr. Jules White gives a 4 minutes intro of Oauth 2.0, it’s a protocol delegation or specification, which is useful for transmitting authorization decisions through Web services and APIs.

Oauth is used by big companies as Google and Facebook among others, also apps that claim to be very safe should use Oauth due to a factor, Cookies are bad!.

When a user logs on to a Web application, the application server sets a value to a cookie that is picked up by the user’s browser. The browser includes the same value of the cookie on each request sent to the same machine until the cookie expires. When the application server receives a request, you can check if cookies that are attributed to it contain a value that identifies a specific user. If there is value in the cookie, then the server can consider the request to be authenticated. This results in certain attacks as man-in-the-middle (MITM), cross-site request forgery (CSRF) and cross-site scripting (XSS). Oauth is designed to avoid this kind of problem.

An illustrative diagram of what we want to achieve in the future from a Android client is the next:

Rest Service with Spring Security

To understand a little this, we will not reinvent the wheel, therefore it will be explained and test a github example wich is a Rest Service with Spring Security and Oauth. Before we must download and install Spring Tool Suite (STS), an IDE focused for Spring Framework programming based in Eclipse (in this tutorial we will use Eclipse STS based in Eclipse Mars 4.5.1).

We need to add Gradle to the STS, for this we must go to menu Help -> Eclipse Market Place and download Gradle IDE Pack.

gradleidepack

Download the example mentioned before before with GIT from terminal (or if you don’t have it, you can download the .zip file).

$ git clone https://github.com/royclarkson/spring-rest-service-oauth.git

Open STS IDE: File -> Import -> Gradle Project. Select file from project, select Build Model and Finish.

gradle1

Now in STS Package Explorer, the project has to be deployed as follows:

gradle2

By default the project is running through the HTTP protocol, so we are going to running through HTTPS that adds security by SSL. Because Oauth without SSL is useless.

For doing this, open application.properties files and modify it as follows:

spring.profiles.active=https

The example comes with its own storage jks key to use SSL, of course this should not be done in a production environment, we must create our own storage keys.

To execute the example, select the project with right click, then go to Run as -> Spring Boot App.

Check everything is running well accesing thorugh browser to URL https://localhost:8443/greeting:

oauth ssl

When executed, it creates a hsqldb database in memory thanks to:

  • build.gradle file has the following content to add the needed dependencies
 compile("org.hsqldb:hsqldb") 
  • In hello.data package has the database entities (Role.java and User.java) and the “repository” (UserRepository.java) where we can implement database CRUD methods (Create, Read, Update and Delete) .
  • Executing import.sql do the necesary inserts to the tables created by the repository.
insert into user(id, name, login, password) values (1,'Roy','roy','spring');
insert into user(id, name, login, password) values (2,'Craig','craig','spring');
insert into user(id, name, login, password) values (3,'Greg','greg','spring');
 
insert into role(id, name) values (1,'ROLE_USER');
insert into role(id, name) values (2,'ROLE_ADMIN');
insert into role(id, name) values (3,'ROLE_GUEST'); 

insert into user_role(user_id, role_id) values (1,1);
insert into user_role(user_id, role_id) values (1,2);
insert into user_role(user_id, role_id) values (2,1);
insert into user_role(user_id, role_id) values (3,1);

Execute from STS the unit test, for this go to the package /src/test/java/hello:

oauth2

Select with right click GreetingControllerTest.java wich is a client class usefull to consume the rest service that is running currently. Go to Run As -> JUnit Test. In JUnit window from STS you can check that everything is running well:

junit1

Lets check how it works everything from terminal using the command curl:

  • The following code will give problems because it needs to enable SSL connection with a valid certificate.
$ curl https://localhost:8443/greeting
curl: (60) SSL certificate problem: self signed certificate
More details here: http://curl.haxx.se/docs/sslcerts.html
...
  • Add the -k option to enable SSL connection without a valid certificate, but equally it is blocking access because we need a valid”Bearer token”. The “Bearer Tokens” are the default type of access tokens. They are automatically activated when an authorization server or server resources are initialized.

$ curl -k https://localhost:8443/greeting

{"error":"unauthorized","error_description":"Full authentication is required to access this resource"}

  • The following example will request access to the service, upon request we will return certain tokens; “access_token” which we will use as a “bearer type” which has a lifetime in seconds indicated in the parameter “expires_in.” “refresh_token” is to be used once expired “bearer token type” to re-ask for a new access token.
$ curl -X POST -k -vu clientapp:123456 https://localhost:8443/oauth/token -H "Accept: application/json" -d "password=spring&username=roy&grant_type=password&scope=read%20write&client_secret=123456&client_id=clientapp"
...
{"access_token":"1075d56b-e5bb-4060-882b-d7096ffe5e75",
"token_type":"bearer",
"refresh_token":"c08387f2-a755-4656-8484-3e19c2703980",
"expires_in":42127,
"scope":"read write"}
  • We use the token of type Bearer to access the resource:
$ curl -k https://localhost:8443/greeting -H "Authorization: Bearer 1075d56b-e5bb-4060-882b-d7096ffe5e75"{"id":1,"content":"Hello, Roy!"}
  • On expiration of the access token we can ask another using the “refresh_token”. It is noteworthy that in the unit test class GreetingControllerTest.java, the getAccessToken() method does all this automatically.
$ curl -X POST -k -vu clientapp:123456 https://localhost:8443/oauth/token -H "Accept: application/json" -d "grant_type=refresh_token&refresh_token=c08387f2-a755-4656-8484-3e19c2703980&client_secret=123456&client_id=clientapp"
...
{"access_token":"2b6e1004-c5b7-4953-b126-3c25564074ee","token_type":"bearer","refresh_token":"c08387f2-a755-4656-8484-3e19c2703980","expires_in":43199,"scope":"read write"}
  • In import.sql we can check that “Roy” user has two roles; rol “ROLE_USER” and “ROLE_ADMIN” in the database. In class OAuth2ServerConfiguration.java, ResourceServerConfiguration method, specifies that only users with rol ADMIN (“ROLE_ is added automatically”) can access to URL “/users” which its controller is UserController.java. The others only can access to “/greeting” , this while they are authenticated correctly:

//...
@Configuration
public class OAuth2ServerConfiguration {
//...
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests()
.antMatchers("/users").hasRole("ADMIN")
.antMatchers("/greeting").authenticated();
// @formatter:on
}

  • Therefore, with “Roy” user we can see what is in the “Users” table thanks to getUsers() method in UserController.java controller. To view the contents from the terminal run:
$ curl -k https://localhost:8443/users -H "Authorization: Bearer 2b6e1004-c5b7-4953-b126-3c25564074ee"[{"id":1,"name":"Roy","login":"roy","password":"spring"},{"id":2,"name":"Craig","login":"craig","password":"spring"},{"id":3,"name":"Greg","login":"greg","password":"spring"}]
  • Assuming you already have an access token for “Craig” user, we can see that this user does not have access to the URL “/users”:
$ curl -k https://localhost:8443/users -H "Authorization: Bearer 86b1a1b6-b9d7-447b-9803-e5fdb5592ca7"
{"error":"access_denied","error_description":"Access is denied"}
  • But “Craig” can access to “/greeting”:
$ curl -k https://localhost:8443/greeting -H "Authorization: Bearer 86b1a1b6-b9d7-447b-9803-e5fdb5592ca7"
{"id":3,"content":"Hello, Craig!"}

The aim of all this has been show fast and introductory the way of how to create a good service with Spring REST and explain what Oauth is.

If you want to connect MySQL or see another way to create services REST with Spring and Oauth , take a look at this code which is a REST service for an APP that I created which stores images uploaded from an Android client, modifies them and sends them back to the client in an encrypted network.

This post is also available in es_ES.

Leave a Reply

Your email address will not be published. Required fields are marked *