Aug 22, 2021

Enable HTTP Basic Authentication in Spring Security

How to enable Spring Security in Java Web application? 

To enable Spring security in Java Web application, you need to configure three things -  (i)  declare a delegating proxy filter in web.xml, (ii) add the ContextLoaderListener in web.xml and (ii) provide actual security constraints on applicationContext-Security.xml file. 

This is also known as Spring's "security chain filter", which relies on web container for initialization of delegating filter proxy.

1) Declare DelegatingFilterProxy filter in web.xml

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>



2) Specify the Spring application context file to ContextLoaderListener

<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
      /WEB-INF/applicationContext.xml
        /WEB-INF/applicationContext-security.xml
    </param-value>
</context-param>

 

3) Specify Spring Security intercept URL pattern in the applicationContext-Security.xml file

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.1.xsd">
    <security:http auto-config="true">
        <security:intercept-url pattern="/admin"
            access="ROLE_ADMIN" />
    </security:http>
    <security:authentication-manager>
        <security:authentication-provider>
            <security:user-service>
                <security:user authorities="ROLE_ADMIN" name="admin"
                    password="admin" />
                <security:user authorities="ROLE_ADMIN" name="root"
                    password="root" />
            </security:user-service>
        </security:authentication-provider>
    </security:authentication-manager>
</beans>

By doing this simple configuration, all URLs ending with /admin to be only accessible with username and password. The two users who have access to this are now admin and root.


How to enable HTTP Basic Authentication in Spring Security using Java and XML Configuration?

Basic authentication is another common ways to authenticate a user in a web application WITHOUT using a form. This is common in the case of RESTful web services clients are not human but application.

In HTTP basic authentication, user login credentials are passed on the HTTP request header, precisely "Authorization" request header. This header sends username/password into request headers, using Base64 encoding.

Other authentication methods include digest authentication, OAuth 2.0, and form-based authentication.

 

To enable HTTP basic authentication using XML config, we use the  <http-basic /> configuration element in Java web app.

To use form login, just replace the <login-form> element in configuration file  applicationContext-security.xml with <http-basic />.

Here is a sample of Spring security configuration with HTTP basic authentication enabled (applicationContext-security.xml):

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
 
<http pattern="/home" security="none"/>
<http use-expressions="true">
  <intercept-url pattern="/**" access="isAuthenticated()" />
  <http-basic />
</http>
 
 
<authentication-manager>
  <authentication-provider>
    <user-service>
      <user name="userId" password="passwd" authorities="ROLE_USER" />
    </user-service>
   </authentication-provider>
</authentication-manager>
 
</beans:beans>

1)The first line says that for /home we don't need any security so anyone can access it.

2)The second line <http> says that we are using Spring expression language and that's why we could have used the isAuthenticated() method for intercepting url.

3) The <intercept-url pattern="/**" access="isAuthenticated()" /> means all URLs need authentication and they will use HTTP basic authentication mechanisms.

4) The authentication manager is not in focus but here we are using in-memory authentication provider with just one user is configured whose username is "userId" and password is "passwd".

To enable HTTP basic autthentication using Java configuration, we configure security aspects of calling the httpBasic()  mehtods on the HttpSecurity object passed into configure() mehtod.

Here is a sample of Spring Security configuration to enable HTTP basic authentication using Java code:

@Configuration
@EnableWebSecurity
public class HttpBasicAuthenticationAdapter extends
    WebSecurityConfigurerAdapter {

  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth)
      throws Exception {
    auth
    .inMemoryAuthentication()
    .withUser("userId").password("passwd")
    .authorities("ROLE_USER");
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
    .authorizeRequests()
    .antMatchers("/securityNone").permitAll()
    .anyRequest().authenticated()
    .and()
    .httpBasic()
    .realmName("Your App");
  }
}

We can combine security constraint using joiner methods like and(). If you want to turn off HTTP basic authentication just remove the call to httpBasic() method and you are done.


Links: