[[servlet-authentication-unpwd]] = Username/Password Authentication :page-section-summary-toc: 1 :figures: images/servlet/authentication/unpwd :icondir: images/icons One of the most common ways to authenticate a user is by validating a username and password. Spring Security provides comprehensive support for authenticating with a username and password. You can configure username and password authentication using the following: .Simple Username/Password Example [tabs] ===== Java:: + [source,java,role="primary"] ---- @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests((authorize) -> authorize .anyRequest().authenticated() ) .httpBasic(Customizer.withDefaults()) .formLogin(Customizer.withDefaults()); return http.build(); } @Bean public UserDetailsService userDetailsService() { UserDetails userDetails = User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build(); return new InMemoryUserDetailsManager(userDetails); } } ---- XML:: + [source,xml,role="secondary"] ---- ---- Kotlin:: + [source,kotlin,role="secondary"] ---- import org.springframework.security.config.annotation.web.invoke @Configuration @EnableWebSecurity class SecurityConfig { @Bean fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { http { authorizeHttpRequests { authorize(anyRequest, authenticated) } formLogin { } httpBasic { } } return http.build() } @Bean fun userDetailsService(): UserDetailsService { val user = User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build() return InMemoryUserDetailsManager(user) } } ---- ===== The preceding configuration automatically registers an xref:servlet/authentication/passwords/in-memory.adoc[in-memory `UserDetailsService`] with the `SecurityFilterChain`, registers the xref:servlet/authentication/passwords/dao-authentication-provider.adoc[`DaoAuthenticationProvider`] with the default xref:servlet/authentication/architecture.adoc#servlet-authentication-authenticationmanager[`AuthenticationManager`], and enables xref:servlet/authentication/passwords/form.adoc[Form Login] and xref:servlet/authentication/passwords/basic.adoc[HTTP Basic] authentication. To learn more about username/password authentication, consider the following use cases: * I want to xref:servlet/authentication/passwords/form.adoc[learn how Form Login works] * I want to xref:servlet/authentication/passwords/basic.adoc[learn how HTTP Basic authentication works] * I want to xref:servlet/authentication/passwords/dao-authentication-provider.adoc[learn how `DaoAuthenticationProvider` works] * I want to xref:servlet/authentication/passwords/in-memory.adoc[manage users in memory] * I want to xref:servlet/authentication/passwords/jdbc.adoc[manage users in a database] * I want to xref:servlet/authentication/passwords/ldap.adoc#servlet-authentication-ldap-authentication[manage users in LDAP] * I want to <> for custom authentication * I want to <> [[publish-authentication-manager-bean]] == Publish an `AuthenticationManager` bean A fairly common requirement is publishing an `AuthenticationManager` bean to allow for custom authentication, such as in a `@Service` or Spring MVC `@Controller`. For example, you may want to authenticate users via a REST API instead of using xref:servlet/authentication/passwords/form.adoc[Form Login]. You can publish such an `AuthenticationManager` for custom authentication scenarios using the following configuration: .Publish `AuthenticationManager` bean for Custom Authentication [tabs] ===== Java:: + [source,java,role="primary"] ---- @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests((authorize) -> authorize .requestMatchers("/login").permitAll() .anyRequest().authenticated() ); return http.build(); } @Bean public AuthenticationManager authenticationManager( UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) { DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); authenticationProvider.setUserDetailsService(userDetailsService); authenticationProvider.setPasswordEncoder(passwordEncoder); return new ProviderManager(authenticationProvider); } @Bean public UserDetailsService userDetailsService() { UserDetails userDetails = User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build(); return new InMemoryUserDetailsManager(userDetails); } @Bean public PasswordEncoder passwordEncoder() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } } ---- XML:: + [source,xml,role="secondary"] ---- ---- Kotlin:: + [source,kotlin,role="secondary"] ---- import org.springframework.security.config.annotation.web.invoke @Configuration @EnableWebSecurity class SecurityConfig { @Bean fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { http { authorizeHttpRequests { authorize("/login", permitAll) authorize(anyRequest, authenticated) } } return http.build() } @Bean fun authenticationManager( userDetailsService: UserDetailsService, passwordEncoder: PasswordEncoder): AuthenticationManager { val authenticationProvider = DaoAuthenticationProvider() authenticationProvider.setUserDetailsService(userDetailsService) authenticationProvider.setPasswordEncoder(passwordEncoder) return ProviderManager(authenticationProvider) } @Bean fun userDetailsService(): UserDetailsService { val user = User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build() return InMemoryUserDetailsManager(user) } @Bean fun passwordEncoder(): PasswordEncoder { return PasswordEncoderFactories.createDelegatingPasswordEncoder() } } ---- ===== With the preceding configuration in place, you can create a `@RestController` that uses the `AuthenticationManager` as follows: .Create a `@RestController` for Authentication [tabs] ===== Java:: + [source,java,role="primary"] ---- @RestController public class LoginController { private final AuthenticationManager authenticationManager; public LoginController(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } @PostMapping("/login") public ResponseEntity login(@RequestBody LoginRequest loginRequest) { Authentication authenticationRequest = UsernamePasswordAuthenticationToken.unauthenticated(loginRequest.username(), loginRequest.password()); Authentication authenticationResponse = this.authenticationManager.authenticate(authenticationRequest); // ... } public record LoginRequest(String username, String password) { } } ---- Kotlin:: + [source,kotlin,role="secondary"] ---- @RestController class LoginController(val authenticationManager: AuthenticationManager) { @PostMapping("/login") fun login(@RequestBody loginRequest: LoginRequest): ResponseEntity { val authenticationRequest = UsernamePasswordAuthenticationToken.unauthenticated( loginRequest.username, loginRequest.password) val authenticationResponse = authenticationManager.authenticate(authenticationRequest) // ... } data class LoginRequest(val username: String, val password: String) } ---- ===== [NOTE] ==== In this example, it is your responsibility to save the authenticated user in the `SecurityContextRepository` if needed. For example, if using the `HttpSession` to persist the `SecurityContext` between requests, you can use xref:servlet/authentication/persistence.adoc#httpsecuritycontextrepository[`HttpSessionSecurityContextRepository`]. ==== [[customize-global-authentication-manager]] == Customize the `AuthenticationManager` Normally, Spring Security builds an `AuthenticationManager` internally composed of a `DaoAuthenticationProvider` for username/password authentication. In certain cases, it may still be desired to customize the instance of `AuthenticationManager` used by Spring Security. For example, you may need to simply disable xref:servlet/authentication/architecture.adoc#servlet-authentication-providermanager-erasing-credentials[credential erasure] for cached users. The recommended way to do this is to simply publish your own `AuthenticationManager` bean, and Spring Security will use it. You can publish an `AuthenticationManager` using the following configuration: .Publish `AuthenticationManager` bean for Spring Security [tabs] ===== Java:: + [source,java,role="primary"] ---- @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests((authorize) -> authorize .requestMatchers("/login").permitAll() .anyRequest().authenticated() ) .httpBasic(Customizer.withDefaults()) .formLogin(Customizer.withDefaults()); return http.build(); } @Bean public AuthenticationManager authenticationManager( UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) { DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); authenticationProvider.setUserDetailsService(userDetailsService); authenticationProvider.setPasswordEncoder(passwordEncoder); ProviderManager providerManager = new ProviderManager(authenticationProvider); providerManager.setEraseCredentialsAfterAuthentication(false); return providerManager; } @Bean public UserDetailsService userDetailsService() { UserDetails userDetails = User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build(); return new InMemoryUserDetailsManager(userDetails); } @Bean public PasswordEncoder passwordEncoder() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } } ---- XML:: + [source,xml,role="secondary"] ---- ---- Kotlin:: + [source,kotlin,role="secondary"] ---- import org.springframework.security.config.annotation.web.invoke @Configuration @EnableWebSecurity class SecurityConfig { @Bean fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { http { authorizeHttpRequests { authorize("/login", permitAll) authorize(anyRequest, authenticated) } formLogin { } httpBasic { } } return http.build() } @Bean fun authenticationManager( userDetailsService: UserDetailsService, passwordEncoder: PasswordEncoder): AuthenticationManager { val authenticationProvider = DaoAuthenticationProvider() authenticationProvider.setUserDetailsService(userDetailsService) authenticationProvider.setPasswordEncoder(passwordEncoder) val providerManager = ProviderManager(authenticationProvider) providerManager.eraseCredentialsAfterAuthentication = false return providerManager } @Bean fun userDetailsService(): UserDetailsService { val user = User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build() return InMemoryUserDetailsManager(user) } @Bean fun passwordEncoder(): PasswordEncoder { return PasswordEncoderFactories.createDelegatingPasswordEncoder() } } ---- ===== Alternatively, you can take advantage of the fact that the `AuthenticationManagerBuilder` used to build Spring Security's global `AuthenticationManager` is published as a bean. You can configure the builder as follows: .Configure global `AuthenticationManagerBuilder` [tabs] ===== Java:: + [source,java,role="primary"] ---- @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { // ... return http.build(); } @Bean public UserDetailsService userDetailsService() { // Return a UserDetailsService that caches users // ... } @Autowired public void configure(AuthenticationManagerBuilder builder) { builder.eraseCredentials(false); } } ---- Kotlin:: + [source,kotlin,role="secondary"] ---- import org.springframework.security.config.annotation.web.invoke @Configuration @EnableWebSecurity class SecurityConfig { @Bean fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { // ... return http.build() } @Bean fun userDetailsService(): UserDetailsService { // Return a UserDetailsService that caches users // ... } @Autowired fun configure(builder: AuthenticationManagerBuilder) { builder.eraseCredentials(false) } } ---- =====