Logging Into a Spring Boot/Elide JSON API Server

DZone 's Guide to

Logging Into a Spring Boot/Elide JSON API Server

Learn how to update the REST API to support authentication and create relationships between entities.

· Integration Zone ·
Free Resource

In the last article, we looked at enabling the POST endpoints in Elide. This worked, but we couldn’t create relationships between entities without configuring Elide’s security model.

Before we can do anything meaningful with Elide’s security model, we first need to update the REST API to support authentication. Without authentication, we have no idea who is attempting to do what with the API, which makes discussions on security meaningless.

Fortunately, Spring makes adding authentication to a Spring Boot application trivial with Spring Security. In order to make use of this Spring library, we first need to add it as a dependency of our project, which we do by adding the following line to the gradle.build file.

compile 'org.springframework.boot:spring-boot-starter-security'

With this library now available within our project, we need to do two things:

  1. Define how we expect users to authenticate
  2. Define the users themselves

Both these tasks are done in a class called WebSecurityConfig, shown below.

In the configure() method we use Spring’s fluent API to define how users will authenticate themselves with our application. Through a series of chained method calls, we disable CSRF, enforce authentication on all requests, and specify that we are making use of HTTP Basic authentication.

We have disabled CSRF because it is awkward to use with a REST API. CSRF is an excellent security measure for websites that want to prevent people from POSTing forms from external sites, but this doesn’t really make sense with an API designed to be called from externally hosted applications.

Basic authentication was selected more for convenience than best practise. You certainly would not want to use Basic authentication over HTTP in a production environment, but for our purposes, it provides us with an easy way for a client application to work with our application.

In the configureGlobal() method we define our users. Again, our chosen solution of an in-memory database of users has been selected for convenience over best practise. Hard coding usernames and passwords have some very obvious drawbacks, but is simple for a proof of concept.

package com.matthewcasperson.elidetest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
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;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

 * This class defines the security that will be applied to our REST API.
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    protected void configure(HttpSecurity http) throws Exception {
                .csrf().disable()               // disable CSRF because it isn't useful for an API
                .anyRequest().authenticated()   // all endpoints require a login
                .httpBasic();                   // we'll make use of Basic HTTP authentication

    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            For our purposes, we'll be using hard coded users. You wouldn't do this in production,
            but it means we don't have to rely on any external dependencies to get security
            up and running.

The addition of the WebSecurityConfig class is all we need to enforce authentication in our REST API. Any request to any endpoint will now require HTTP Basic authentication details matching one of our users or it will be rejected.

The last thing we want to do is obtain the details of the logged in user, and pass them to Elide. If you look at our previous articles, you’ll notice that we have been supplying a new Object() to the Elide opaqueUser parameter. This is because we needed to supply something, but until now have not had any object that represents the user.

Now that all endpoints require authentication, we can add a principal parameter to the REST API methods, and Spring will inject the details of the current user. This principle object will be what we pass to Elide in order to perform some security checks. The code below shows the new jsonApiGet() method taking the newly added principle parameter, and passing it to the Elide get() method.

    @CrossOrigin(origins = "*")
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_VALUE,
            value={"/{entity}", "/{entity}/{id}/relationships/{entity2}", "/{entity}/{id}/{child}", "/{entity}/{id}"})
    public String jsonApiGet(
            @RequestParam final Map<String, String> allRequestParams,
            final HttpServletRequest request,
            final Principal principal) {
            Here we pass through the data Spring has provided for us in the parameters, then making
            use of Java 8 Lambdas to do something useful.
        return elideRunner(
                (elide, path) -> elide.get(path, fromMap(allRequestParams), principal).getBody());

With authentication in place and a real user object to pass to Elide, we can move on to the next article to configuring Elide’s security options.

Download the source code for this project from GitHub.

json api, security, spring

Published at DZone with permission of Matthew Casperson , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}