[JAVA] Implementation sample when Form authentication and Request-Header authentication are used together in Spring Security

Trigger In a certain Web application development, there was a requirement to realize the following two at the same time. ① Form authentication can be performed by entering the ID and password from the login screen. (2) Authentication can be performed with the value of a specific attribute in the HTTP request header.

(2) is a requirement that the existing external authentication system sets a token in the HTTP request header and redirects when the authentication is successful, so SSO using it is realized.

(1) Independent or (2) Independent implementation samples can be found all over the Internet, but I could not find a pattern to use them together (and it was technical as such), so I will introduce how it was realized.

Source Set as follows. https://github.com/ShandyGaffLover/sample001/blob/master/src/main/resources/spring-security.xml

Explanation Customize "PRE_AUTH_FILTER" and "FORM_LOGIN_FILER".
    <sec:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
    <sec:custom-filter position="FORM_LOGIN_FILTER" ref="formLoginFilter" />

Customize PRE_AUTH_FILTER

To customize "PRE_AUTH_FILTER", use the RequestHeaderAuthenticationFilter class as follows. Set the exceptionIfHeaderMissing property to false and the continueFilterChainOnUnsuccessfulAuthentication property to true for convenience with Form authentication.

  <bean id="siteminderFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
    <property name="principalRequestHeader" value="SM_USER"/>
    <property name="authenticationManager" ref="sm_authenticationManager" />
    <property name="exceptionIfHeaderMissing" value="false"/>

    <property name="continueFilterChainOnUnsuccessfulAuthentication" value="true"/>
  </bean>

Here, AuthenticationManager (and AuthenticationProvider) is defined as follows.

  <sec:authentication-manager id="sm_authenticationManager">
    <sec:authentication-provider ref="preauthAuthProvider" />
  </sec:authentication-manager>

  <bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
    <property name="preAuthenticatedUserDetailsService">
      <bean id="userDetailsServiceWrapper"
          class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
        <property name="userDetailsService" ref="customUserDetailsService"/>
      </bean>
    </property>
  </bean>

Use the PreAuthenticatedAuthenticationProvider class for AuthenticationProvider. Note that the UserDetailsService given to the preAuthenticatedUserDetailsService property must be wrapped by the UserDetailsByNameServiceWrapper class.

Customize FORM_LOGIN_FILER The customization of "FORM_LOGIN_FILER" is as follows.
 <sec:authentication-manager id="form_authenticationManager">
    <sec:authentication-provider  user-service-ref="customUserDetailsService" >
    </sec:authentication-provider>
  </sec:authentication-manager>

  <bean id="formLoginFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <property name="authenticationManager" ref="form_authenticationManager" />
    <property name="authenticationSuccessHandler" ref="formLoginSuccessHandler" />
    <property name="authenticationFailureHandler" ref="formLoginFailureHandler" />
    <property name="filterProcessesUrl" value="/login" />
  </bean>

Note that since a custom filter is used here, it is necessary to set the entry-point-ref attribute of the tag as shown below.

  <sec:http auto-config="false" use-expressions="true" entry-point-ref="loginUrlAuthenticationEntryPoint">

  ~Omission~

    <sec:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
    <sec:custom-filter position="FORM_LOGIN_FILTER" ref="formLoginFilter" />
  </sec:http>

  <bean id="loginUrlAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <constructor-arg value="/loginPage" />
  </bean>

real thing You can check the operation from the following. [^ 1] https://shandygafflover.herokuapp.com/

① From the login screen, enter "user" for username and "password" for password to log in and you will be authenticated. (2) If you set the value "user" to the attribute "SM_USER" in the HTTP request header [^ 2], you will be authenticated. Here, ModHeader introduced in the following article is used.

Set the authentication information from the outside in the HTTP header of the browser --Qiita  https://qiita.com/utwang/items/1eeb25d27e8acea33a8a

[^ 1]: I'm very sorry, but at the time of posting the article, it is said that it does not support https (even though it is authentication!). I'm sorry. I will make time to deal with it.

[^ 2]: The attribute name "SM_USER" in the request header is just an example. In actual development, attribute names should be difficult to guess and should be confidential.

Execution result Set the value "user" to the attribute "SM_USER" of the HTTP request header. ![requestheader.png](https://qiita-image-store.s3.amazonaws.com/0/322008/7b04e084-5929-255d-8d10-7ee600665ee6.png)

In this state, for example, access the following URL. url.png

Then you will be authenticated and the page will be displayed. greeting.png

If the attribute "SM_USER" is not set in the HTTP request header, the login screen will be displayed, so you will be authenticated by username and password. login.png greeting.png

Reference URL

Spring Security Usage Memo Authentication / Authorization --Qiita https://qiita.com/opengl-8080/items/032ed0fa27a239bdc1cc

03-1. How to set Spring Security 2 --soracane https://sites.google.com/site/soracane/home/springnitsuite/spring-security/spring-securityno-settei-houhou

Tech Note – Explains how to create your own spring security authentication process http://javatechnology.net/spring/spring-security-login-filter-original/

Work notes when applying Spring Security-Namihira Blog http://namihira.hatenablog.com/entry/20160817/1471396975

AbstractAuthenticationProcessingFilter (Spring Security 4.2.6.RELEASE API) https://docs.spring.io/spring-security/site/docs/4.2.6.RELEASE/apidocs/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.html

Spring Security Java - Multiple Authentication Manager - 2 bean found error - Stack Overflow https://stackoverflow.com/questions/32105846/spring-security-java-multiple-authentication-manager-2-bean-found-error

Recommended Posts

Implementation sample when Form authentication and Request-Header authentication are used together in Spring Security
Error in implementation when implementing Spring validation
Create API key authentication for Web API in Spring Security
About Spring Security authentication