spring-projects/spring-security · error · AuthenticationServiceException
Authentication method not supported
Error message
Authentication method not supported: ${request.method} What it means
UsernamePasswordAuthenticationFilter.attemptAuthentication() only accepts POST requests when postOnly is true (the default). Any other HTTP method (GET, PUT, ...) throws AuthenticationServiceException with the offending method, which surfaces as HTTP 500 unless handled, rather than a normal authentication failure.
Solutions
- Set the login form/HTTP client to POST: <form method="post" action="/login">
- If non-POST methods are genuinely required, call filter.setPostOnly(false)
- For JSON login, use a filter configured with an appropriate converter rather than form login, or a custom attemptAuthentication
- Check for redirects (301/302) that convert POST to GET and fix the client to POST directly to the target
Example fix
// before <form action="/login"> ... </form> // after <form method="post" action="/login"> ... </form>
Defensive patterns
Strategy: validation
Validate before calling
if (!"POST".equalsIgnoreCase(request.getMethod())) {
throw new IllegalStateException("Login must be submitted via POST");
} Try / catch
try {
chain.doFilter(request, response, chain);
} catch (AuthenticationServiceException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Authentication method not supported")) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
}
throw e;
} Prevention
- Always set method="post" on login forms
- Never trigger login via links/GET requests
- Call setPostOnly(false) only deliberately
- Check redirects do not downgrade POST to GET
When it happens
Trigger: Submitting the login form via GET (missing method="POST" on the form), a redirect turning POST into GET, API clients calling the login URL with the wrong verb, or postOnly left default while the frontend uses another method.
Common situations: HTML forms without an explicit method attribute default to GET; login links (href) instead of form submissions; misconfigured proxies/CDNs rewriting methods; custom frontends sending PUT/JSON to the form-login endpoint.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- The request was rejected because the HTTP method
- 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…
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/92844b6405677367.
Report an issue: GitHub.
Appendix: source
Thrown at web/src/main/java/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilter.java:77
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
private boolean postOnly = true;
public UsernamePasswordAuthenticationFilter() {
super(DEFAULT_PATH_REQUEST_MATCHER);
}
public UsernamePasswordAuthenticationFilter(AuthenticationManager authenticationManager) {
super(DEFAULT_PATH_REQUEST_MATCHER, authenticationManager);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
if (this.postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
username = (username != null) ? username.trim() : "";
String password = obtainPassword(request);
password = (password != null) ? password : "";
UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username,
password);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
/**
* Enables subclasses to override the composition of the password, such as by
* including additional values and a separator.
* <p>
* This might be used for example if a postcode/zipcode was required in addition to
* the password. A delimiter such as a pipe (|) should be used to separate theView on GitHub (pinned to 96852e8860)