[JAVA] Set Spring Security authentication result to JSON

Introduction

In Spring Security, I tried to find out how to return the result of Form authentication in JSON.

The version I verified is as follows.

Version
Java 1.8
Spring Boot 1.5.10.RELEASE

Sample code

Code from theory. Please see the sample code first.

JsonAuthConfigurer.java


package example;

import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

@Configuration
public class JsonAuthConfigurer extends WebSecurityConfigurerAdapter
    implements AuthenticationSuccessHandler, AuthenticationFailureHandler {
  private static final MediaType CONTENT_TYPE_JSON = MediaType.APPLICATION_JSON_UTF8;

  @Autowired
  MappingJackson2HttpMessageConverter httpMessageConverter;

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.formLogin() //Set Form authentication
        .successHandler(this) //Handler specification when authentication is successful
        .failureHandler(this); //Handler specification when authentication fails
    http.authorizeRequests().anyRequest().authenticated(); //Setting of requests that require authentication
  }


  // ------------------------------
  // AuthenticationSuccessHandler
  // ------------------------------

  @Override
  public void onAuthenticationSuccess(HttpServletRequest request,
                                      HttpServletResponse response,
                                      Authentication authentication) throws IOException {
    MyResult result = new MyResult("Authentication successful"); //Object to be JSON
    HttpOutputMessage outputMessage = new ServletServerHttpResponse(response);
    httpMessageConverter.write(result, CONTENT_TYPE_JSON, outputMessage); //Write to Response
    response.setStatus(HttpStatus.OK.value()); // 200 OK.
  }

  // ------------------------------
  // AuthenticationFailureHandler
  // ------------------------------

  @Override
  public void onAuthenticationFailure(HttpServletRequest request,
                                      HttpServletResponse response,
                                      AuthenticationException exception) throws IOException {
    MyResult result = new MyResult("Authentication failure"); //Object to be JSON
    HttpOutputMessage outputMessage = new ServletServerHttpResponse(response);
    httpMessageConverter.write(result, CONTENT_TYPE_JSON, outputMessage); //Write to Response
    response.setStatus(HttpStatus.UNAUTHORIZED.value()); // 401 Unauthorized.
  }


  // ------------------------------

  /**Authentication result*/
  @lombok.Value
  public static class MyResult {
    private final String message;
  }

}

To make Response JSON

It seems that you should write JSON in the Response content with successHandler [^ fqcn-s] and failureHandler [^ fqcn-f]. Also, in case of authentication failure, the status is set to "401 Unauthorized."

Tips Since the process to make Response into JSON has been completed easily, I will introduce the tips that I noticed after trying various things.

MappingJackson2HttpMessageConverter When writing JSON to the Response content, it is convenient to use MappingJackson2HttpMessageConverter. It will also automatically add Content-Type: application / json; charset = UTF-8 to the header.

Autowired MappingJackson2HttpMessageConverter


@Autowired
MappingJackson2HttpMessageConverter httpMessageConverter;

Write JSON


httpMessageConverter.write(result, CONTENT_TYPE_JSON, outputMessage);

By the way, if you write to Response by yourself, it will be as follows. [^ quote-1]

@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
  response.getWriter().write(new ObjectMapper().writeValueAsString(new UserAuthenticationResponse(authentication.getName(), 123l)));
  response.setStatus(200);
}

Handler Interface implementation

As shown in the sample code above, implementing the Interface of various handlers in the implementation class of WebSecurityConfigurer will make the code cleaner.

Excerpt of a clean part


@Configuration
public class JsonAuthConfigurer extends WebSecurityConfigurerAdapter
    implements AuthenticationSuccessHandler, AuthenticationFailureHandler {
    //↑ Because the handler is implemented in this class...

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.formLogin()
        .successHandler(this) //← The argument of the handler specification may be this
        .failureHandler(this); //← The argument of the handler specification may be this
  }

  //...
}

in conclusion

This is the third certification series. Past articles are as follows.

-Use Basic Authentication with Spring Boot -How to implement authentication process by specifying user name and password in Spring Boot

I feel like I'm getting used to Spring.

Recommended Posts

Set Spring Security authentication result to JSON
About Spring Security authentication
[Introduction to Spring Boot] Authentication function with Spring Security
Spring Security usage memo Authentication / authorization
Implemented authentication function with Spring Security ②
Implemented authentication function with Spring Security ③
Spring Boot Tutorial Using Spring Security Authentication
How to set Spring Boot + PostgreSQL
Implemented authentication function with Spring Security ①
Learn Spring Security authentication processing architecture
Authentication / authorization with Spring Security & Thymeleaf
DB authentication with Spring Security & hashing with BCrypt
Achieve BASIC authentication with Spring Boot + Spring Security
[Reverse lookup] Spring Security (updated from time to time)
Try LDAP authentication with Spring Security (Spring Boot) + OpenLDAP
Add your own authentication items with Spring Security
Spring Boot --How to set session timeout time
How to set Dependency Injection (DI) for Spring Boot
Try to work with Keycloak using Spring Security SAML (Spring 5)
Create API key authentication for Web API in Spring Security
Set RSpec to DRY
A new employee tried to create an authentication / authorization function from scratch with Spring Security
Spring Security causes 403 forbidden
Authenticate 3 or more parameters in JSON format using Spring Security
Create API to send and receive Json data in Spring
Set up Multipart Resolver to allow file uploads in Spring
How to set up a proxy with authentication in Feign