spring-projects/spring-security · error · BeanDefinitionStoreException
You cannot use bearer-token-ref and…
Error message
You cannot use bearer-token-ref and authentication-converter-ref in the same oauth2-resource-server element
What it means
The <oauth2-resource-server> XML element supports configuring bearer token resolution either via bearer-token-ref or converting the request via authentication-converter-ref — but not both simultaneously. parse() (OAuth2ResourceServerBeanDefinitionParser.java:133) throws BeanDefinitionStoreException when both attributes are present, because combining them would create ambiguous authentication handling.
Solutions
- Remove bearer-token-ref and keep only authentication-converter-ref.
- Alternatively remove authentication-converter-ref and keep only bearer-token-ref.
- If both behaviors are needed, implement a custom authentication converter that internally uses the desired BearerTokenResolver.
Example fix
// before <oauth2-resource-server bearer-token-ref="myResolver" authentication-converter-ref="myConverter"/> // after <oauth2-resource-server authentication-converter-ref="myConverter"/>
Defensive patterns
Strategy: validation
Validate before calling
Element el = /* oauth2-resource-server element */;
if (el.hasAttribute("bearer-token-ref") && el.hasAttribute("authentication-converter-ref")) {
throw new IllegalArgumentException("bearer-token-ref and authentication-converter-ref are mutually exclusive");
} Try / catch
try { new OAuth2ResourceServerBeanDefinitionParser().parse(el, pc); } catch (BeanDefinitionStoreException e) { if (e.getMessage().contains("bearer-token-ref")) { log.error("Remove one of bearer-token-ref / authentication-converter-ref", e); } throw e; } Prevention
- Set at most one of bearer-token-ref / authentication-converter-ref per <oauth2-resource-server>
- When migrating to authentication-converter-ref, delete the old bearer-token-ref attribute
- Document in your security config which token-handling mechanism is in use
When it happens
Trigger: Defining <oauth2-resource-server bearer-token-ref="..." authentication-converter-ref="..."/> in the XML namespace; both getBearerTokenResolver and getAuthenticationConverter return non-null from the same element.
Common situations: Copy-pasting attributes from two config examples; migrating from a bearer-token setup to an authentication-converter setup while leaving the old attribute in place.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- A Bean named mvcHandlerMappingIntrospector of type…
- A Bean named mvcHandlerMappingIntrospector of type…
- A filter chain that matches any request
- A ReactiveSessionRegistry is needed for concurrent session…
- A ServerOneTimeTokenGenerationSuccessHandler is required to…
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/d07d4e7b44241cd8.
Report an issue: GitHub.
Appendix: source
Thrown at config/src/main/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParser.java:133
public BeanDefinition parse(Element oauth2ResourceServer, ParserContext pc) {
Element jwt = DomUtils.getChildElementByTagName(oauth2ResourceServer, Elements.JWT);
Element opaqueToken = DomUtils.getChildElementByTagName(oauth2ResourceServer, Elements.OPAQUE_TOKEN);
validateConfiguration(oauth2ResourceServer, jwt, opaqueToken, pc);
if (jwt != null) {
BeanDefinition jwtAuthenticationProvider = new JwtBeanDefinitionParser().parse(jwt, pc);
this.authenticationProviders.add(new RuntimeBeanReference(
pc.getReaderContext().registerWithGeneratedName(jwtAuthenticationProvider)));
}
if (opaqueToken != null) {
BeanDefinition opaqueTokenAuthenticationProvider = new OpaqueTokenBeanDefinitionParser().parse(opaqueToken,
pc);
this.authenticationProviders.add(new RuntimeBeanReference(
pc.getReaderContext().registerWithGeneratedName(opaqueTokenAuthenticationProvider)));
}
BeanMetadataElement bearerTokenResolver = getBearerTokenResolver(oauth2ResourceServer);
BeanMetadataElement authenticationConverter = getAuthenticationConverter(oauth2ResourceServer);
if (bearerTokenResolver != null && authenticationConverter != null) {
throw new BeanDefinitionStoreException(
"You cannot use bearer-token-ref and authentication-converter-ref in the same oauth2-resource-server element");
}
if (bearerTokenResolver == null && authenticationConverter == null) {
authenticationConverter = new RootBeanDefinition(BearerTokenAuthenticationConverter.class);
}
BeanMetadataElement authenticationEntryPoint = getEntryPoint(oauth2ResourceServer);
BeanDefinition requestMatcher = buildRequestMatcher(bearerTokenResolver, authenticationConverter);
this.entryPoints.put(requestMatcher, authenticationEntryPoint);
this.deniedHandlers.put(requestMatcher, this.accessDeniedHandler);
this.ignoreCsrfRequestMatchers.add(requestMatcher);
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder
.rootBeanDefinition(BearerTokenAuthenticationFilter.class);
BeanMetadataElement authenticationManagerResolver = getAuthenticationManagerResolver(oauth2ResourceServer);
filterBuilder.addConstructorArgValue(authenticationManagerResolver);
filterBuilder.addPropertyValue(AUTHENTICATION_ENTRY_POINT, authenticationEntryPoint);
filterBuilder.addPropertyValue("securityContextHolderStrategy",
this.authenticationFilterSecurityContextHolderStrategy);
View on GitHub (pinned to 96852e8860)