diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/multipleauthproviders/CustomAuthenticationProvider.java b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleauthproviders/CustomAuthenticationProvider.java
new file mode 100644
index 0000000000..1a89c362cd
--- /dev/null
+++ b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleauthproviders/CustomAuthenticationProvider.java
@@ -0,0 +1,31 @@
+package org.baeldung.multipleauthproviders;
+
+import java.util.Collections;
+
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CustomAuthenticationProvider implements AuthenticationProvider {
+ @Override
+ public Authentication authenticate(Authentication auth) throws AuthenticationException {
+ final String username = auth.getName();
+ final String password = auth.getCredentials()
+ .toString();
+
+ if ("externaluser".equals(username) && "pass".equals(password)) {
+ return new UsernamePasswordAuthenticationToken(username, password, Collections.emptyList());
+ } else {
+ throw new BadCredentialsException("External system authentication failed");
+ }
+ }
+
+ @Override
+ public boolean supports(Class> auth) {
+ return auth.equals(UsernamePasswordAuthenticationToken.class);
+ }
+}
diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/multipleauthproviders/MultipleAuthController.java b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleauthproviders/MultipleAuthController.java
new file mode 100644
index 0000000000..80573c1c7d
--- /dev/null
+++ b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleauthproviders/MultipleAuthController.java
@@ -0,0 +1,13 @@
+package org.baeldung.multipleauthproviders;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class MultipleAuthController {
+
+ @RequestMapping("/api/ping")
+ public String getPing() {
+ return "OK";
+ }
+}
\ No newline at end of file
diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/multipleauthproviders/MultipleAuthProvidersApplication.java b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleauthproviders/MultipleAuthProvidersApplication.java
new file mode 100644
index 0000000000..077f558bd2
--- /dev/null
+++ b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleauthproviders/MultipleAuthProvidersApplication.java
@@ -0,0 +1,12 @@
+package org.baeldung.multipleauthproviders;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+// @ImportResource({ "classpath*:spring-security-multiple-auth-providers.xml" })
+public class MultipleAuthProvidersApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(MultipleAuthProvidersApplication.class, args);
+ }
+}
diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/multipleauthproviders/MultipleAuthProvidersSecurityConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleauthproviders/MultipleAuthProvidersSecurityConfig.java
new file mode 100644
index 0000000000..432cc61e87
--- /dev/null
+++ b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleauthproviders/MultipleAuthProvidersSecurityConfig.java
@@ -0,0 +1,34 @@
+package org.baeldung.multipleauthproviders;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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;
+
+@EnableWebSecurity
+public class MultipleAuthProvidersSecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Autowired
+ CustomAuthenticationProvider customAuthProvider;
+
+ @Override
+ public void configure(AuthenticationManagerBuilder auth) throws Exception {
+
+ auth.authenticationProvider(customAuthProvider);
+
+ auth.inMemoryAuthentication()
+ .withUser("memuser")
+ .password("pass")
+ .roles("USER");
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.httpBasic()
+ .and()
+ .authorizeRequests()
+ .antMatchers("/api/**")
+ .authenticated();
+ }
+}
diff --git a/spring-security-mvc-boot/src/main/resources/spring-security-multiple-auth-providers.xml b/spring-security-mvc-boot/src/main/resources/spring-security-multiple-auth-providers.xml
new file mode 100644
index 0000000000..4cfa6bbf26
--- /dev/null
+++ b/spring-security-mvc-boot/src/main/resources/spring-security-multiple-auth-providers.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-security-mvc-boot/src/test/java/org/baeldung/web/MultipleAuthProvidersApplicationTests.java b/spring-security-mvc-boot/src/test/java/org/baeldung/web/MultipleAuthProvidersApplicationTests.java
new file mode 100644
index 0000000000..0d70cd64e4
--- /dev/null
+++ b/spring-security-mvc-boot/src/test/java/org/baeldung/web/MultipleAuthProvidersApplicationTests.java
@@ -0,0 +1,61 @@
+package org.baeldung.web;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Collections;
+
+import org.baeldung.multipleauthproviders.MultipleAuthProvidersApplication;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = MultipleAuthProvidersApplication.class)
+public class MultipleAuthProvidersApplicationTests {
+ @Autowired
+ private TestRestTemplate restTemplate;
+
+ @Test
+ public void givenMemUsers_whenGetPingWithValidUser_thenOk() {
+ ResponseEntity result = makeRestCallToGetPing("memuser", "pass");
+
+ assertThat(result.getStatusCodeValue()).isEqualTo(200);
+ assertThat(result.getBody()).isEqualTo("OK");
+ }
+
+ @Test
+ public void givenExternalUsers_whenGetPingWithValidUser_thenOK() {
+ ResponseEntity result = makeRestCallToGetPing("externaluser", "pass");
+
+ assertThat(result.getStatusCodeValue()).isEqualTo(200);
+ assertThat(result.getBody()).isEqualTo("OK");
+ }
+
+ @Test
+ public void givenAuthProviders_whenGetPingWithNoCred_then401() {
+ ResponseEntity result = makeRestCallToGetPing();
+
+ assertThat(result.getStatusCodeValue()).isEqualTo(401);
+ }
+
+ @Test
+ public void givenAuthProviders_whenGetPingWithBadCred_then401() {
+ ResponseEntity result = makeRestCallToGetPing("user", "bad_password");
+
+ assertThat(result.getStatusCodeValue()).isEqualTo(401);
+ }
+
+ private ResponseEntity makeRestCallToGetPing(String username, String password) {
+ return restTemplate.withBasicAuth(username, password)
+ .getForEntity("/api/ping", String.class, Collections.emptyMap());
+ }
+
+ private ResponseEntity makeRestCallToGetPing() {
+ return restTemplate.getForEntity("/api/ping", String.class, Collections.emptyMap());
+ }
+}