spring-projects/spring-security · error · NoSuchBeanDefinitionException

Did you forget to add a global <authentication-manager> elem

Error message

Did you forget to add a global <authentication-manager> element to your configuration (with child <authentication-provider> elements)? Alternatively you can use the authentication-manager-ref attribute on your <http> and <global-method-security> elements.

What it means

AuthenticationManagerFactoryBean.getObject resolves the internal AuthenticationManager bean named 'authenticationManager'. If that bean is missing and no unique UserDetailsService bean exists to build a default DaoAuthenticationProvider, it throws NoSuchBeanDefinitionException carrying the long hint about adding a global <authentication-manager> element or using authentication-manager-ref. This is Spring Security XML namespace configuration failing to produce any authentication source.

Source

Thrown at config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java:66

	private ObservationRegistry observationRegistry = ObservationRegistry.NOOP;

	public static final String MISSING_BEAN_ERROR_MESSAGE = "Did you forget to add a global <authentication-manager> element "
			+ "to your configuration (with child <authentication-provider> elements)? Alternatively you can use the "
			+ "authentication-manager-ref attribute on your <http> and <global-method-security> elements.";

	@Override
	public AuthenticationManager getObject() throws Exception {
		try {
			return (AuthenticationManager) this.bf.getBean(BeanIds.AUTHENTICATION_MANAGER);
		}
		catch (NoSuchBeanDefinitionException ex) {
			if (!BeanIds.AUTHENTICATION_MANAGER.equals(ex.getBeanName())) {
				throw ex;
			}
			UserDetailsService uds = this.bf.getBeanProvider(UserDetailsService.class).getIfUnique();
			if (uds == null) {
				throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER, MISSING_BEAN_ERROR_MESSAGE);
			}
			DaoAuthenticationProvider provider = new DaoAuthenticationProvider(uds);
			PasswordEncoder passwordEncoder = this.bf.getBeanProvider(PasswordEncoder.class).getIfUnique();
			if (passwordEncoder != null) {
				provider.setPasswordEncoder(passwordEncoder);
			}
			provider.afterPropertiesSet();
			ProviderManager manager = new ProviderManager(Arrays.asList(provider));
			if (this.observationRegistry.isNoop()) {
				return manager;
			}
			return new ObservationAuthenticationManager(this.observationRegistry, manager);
		}
	}

	@Override
	public Class<? extends AuthenticationManager> getObjectType() {
		return ProviderManager.class;

View on GitHub (pinned to 96852e8860)

Solutions

  1. Add a global <authentication-manager> element with at least one <authentication-provider> child to the XML configuration.
  2. Alternatively, set authentication-manager-ref on <http> (and <global-method-security>) to point at an explicitly defined AuthenticationManager bean.
  3. If relying on the UserDetailsService fallback, ensure exactly one UserDetailsService bean exists in the context (remove or qualify duplicates with @Primary).
  4. Optionally register a PasswordEncoder bean so the auto-built DaoAuthenticationProvider decodes passwords correctly.

Example fix

<!-- before: no authentication source defined -->
<http auto-config="true"/>
<!-- after -->
<http auto-config="true"/>
<authentication-manager>
  <authentication-provider>
    <user-service>
      <user name="user" password="{noop}password" authorities="ROLE_USER"/>
    </user-service>
  </authentication-provider>
</authentication-manager>
Defensive patterns

Strategy: validation

Validate before calling

// Verify exactly one UserDetailsService and an AuthenticationManager are reachable
long udsCount = context.getBeanProvider(UserDetailsService.class).stream().count();
boolean authManagerDefined = context.containsBean("authenticationManager")
    || context.getBeanNamesForType(AuthenticationManager.class).length > 0;
if (udsCount != 1 && !authManagerDefined) {
    throw new IllegalStateException(
        "Define a global <authentication-manager> or provide exactly one UserDetailsService bean");
}

Try / catch

try {
    AuthenticationManager am = context.getBean("org.springframework.security.authenticationManager",
        AuthenticationManager.class);
} catch (NoSuchBeanDefinitionException e) {
    if ("org.springframework.security.authenticationManager".equals(e.getBeanName())) {
        throw new IllegalStateException("Missing <authentication-manager>; add one with an <authentication-provider>", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: XML config has <http> or <global-method-security> that needs an AuthenticationManager, but there is no <authentication-manager> element and no exactly-one UserDetailsService bean in the context (zero or multiple candidates), so getObject cannot build a DaoAuthenticationProvider fallback.

Common situations: Migrating old XML security configs where the <authentication-manager> block was deleted; defining several UserDetailsService beans (e.g. two @Bean user detail services) so getIfUnique() returns null; using <http> without any authentication source at all.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/3a8a3cc6b343df10. Report an issue: GitHub.