Spring boot rest api examples

How to secure a REST API
Since our TEST service accepts user registrations, we have to think about protection of data. Before a user can retrieve his data, he has to authorize himself. In the world of a REST service, sessions in the classical sense do not exist. Every call has to be authorized to access the resource.

Several practices are common. Often, services are protected by Basic Auth. Basic Auth requires the client to send the username and password with each request (Base64 encoded as part of the header information).

A sniffer could use that information to authorize his calls. Even if we would protect our service by SSL, we decided that Basic Auth was not the right approach for our service. Another method is to use a token, which will be changed with each request.

A successful request would return the next token together with the response. In this case, parallel requests or errors could easily lead to a logout. That’s why we decided to use OAuth 2.0. OAuth 2.0 uses the password only for the initial login.

The OAuth login will return 2 tokens. Future requests have to be executed with the first token (Access Token). This token replaces the password for a given period of time. If someone would be able to intercept the traffic, he could use that token for that timeframe until the token expires. As soon as the token expires, the client can retrieve a new token by using the second token (refresh token).

This concept does not force the client to send the real password all the time and parallel execution of calls is doable as well. Even if the access token expires, the client can assure that the user is logged in permanently by using the refresh token. The tokens send to the client need to be persisted in order to compare the token send by the client with the generated one. In our use case, we wanted to get rid of any database, since this service was only a wrapper for other microservices which contain the real logic.

In order to solve this, we had three options. We could use an in-memory database, which is shared between several instances. A second option would have been to use a load balancing which sends all requests from a session always to the same instance which stores the token locally (e.g. in memory). The first option would lead to unnecessary efforts, the second one breaks with the whole concept of cloud-native microservice architectures because then we would not have a stateless application anymore.

Every downtime would mean a log out of customers. So we decided to use another approach. The JWT (JSON Web Tokens) extension on top of OAuth allows the authorization without storing the tokens. An access token is not just randomly generated, instead, the user ID, the expiry date, and other Metacloud-native is signed with a private key and added to the header information as Oauth token. This way every instance can verify the validity of the token and retrieve the user information without storing the token and the information is encrypted. JWT is fully compliant with the OAuth format, which means all OAuth 2 clients should be able to use JWT even without knowing that the token is a JWT token and not a classical OAuth 2.0 token.


The format stays the same, the token is just a little bit longer. In our case, the client didn’t have to make any changes needed and even in the REST service, the needed adaptions were minimal. Instead of comparing the received token with the stored token, a JWT repository is called to verify the token. The repository decrypts the token and behaves equally to a repository which would use a database. The token contains the user ID but not the user data itself. That means the storage of user data must be solved independently. In our case, the service routed the user data via rest to a user service. Listing 6 shows the Spring Boot configuration needed to use OAuth 2.0 with JWT. It shows some additional configuration options as well.

In the below examples oauth,

@Configuration
public class OAuth2ServerConfiguration {
...
@Bean
public JwtAccessTokenConverter getTokenConverter() {
JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter();
// for asymmetric signing/verification use
// tokenConverter.setKeyPair(...);
tokenConverter.setSigningKey("aTokenSigningKey");
tokenConverter.setVerifierKey("aTokenSigningKey");
return tokenConverter;
}
...
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends
ResourceServerConfigurerAdapter {

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

http.authorizeRequests()
.antMatchers("/register/**")
.permitAll()
.antMatchers("/user/**")
.access("#oauth2.hasScope('read')");
}

}

@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends
AuthorizationServerConfigurerAdapter {

...
@Override
public void configure(ClientDetailsServiceConfigurer clients)
throws Exception {
clients
.inMemory()
.withClient("aClient")
.authorizedGrantTypes("password", "refresh_token")
.authorities("USER")
.scopes("read", "write")
.resourceIds(RESOURCE_ID)
.secret("aSecret");
}
...
}

}

OAuth 2.0 enables authorization with a 3rd party. Even if this feature is unused in this case, we can limit the usage of our REST service to certain clients or partners. In the login phase, not only the username and password of the user must be transmitted, additionally, a client and a client password are needed. In our cases, the clients are the different apps. Spring Boot offers a simple roles and rights model. But we are not going into details in this tutorial. In our example, the registration is not secured, but accessing user data is only possible after a successful login. The login is, in this case, the request to retrieve an access OAuth-2.0 token. Listing 7 shows a login and the retrieval of user information after login with the OAuth token

 

For More:

Spring boot rest api example

Spring interview questions and answers

 

Source taken:jaxender