Summary
OPTIONS header does not take user access into account to fill in Allow header in response.
Actual Behavior
From the documentation, we can assume that calling a Spring controller with OPTIONS HTTP method returns all the methods mapped by @RequestMapping annotation, plus OPTIONS itself and HEAD.
But when enabling Spring Security and declaring some restrictions through a class extending WebSecurityConfigurerAdapter's configure(HttpSecurity http) method, we are able to restrict the allowed HTTP methods a user (either anonymous or authenticated with a given role) can access to for a given resource. However, the Allow header content in the response to an OPTIONS request does not vary based on those restrictions.
Expected Behavior
Having the Allow header content varying based on user access.
Sample
Here is a sample project to demonstrate the behavior: https://github.com/Alexandre-Carbenay/spring-security-options-method
After starting the application, you can curl -v -X OPTIONS http://localhost:8080/hellos. It should provide:
HTTP/1.1 200
Allow: GET,HEAD,OPTIONS
but actually provides:
HTTP/1.1 200
Allow: GET,HEAD,POST,OPTIONS
whereas with the following curl -v -X OPTIONS http://localhost:8080/hellos -H "Authorization: Basic $(echo -n 'user:password' | base64)", you should indeed get the POST method in Allow header
Comment From: eleftherias
Thanks for getting in touch, however the current behaviour is the expected behaviour.
The Allow header lists the set of methods supported by the given endpoint, not the methods that the currently authenticated user has access to.
Could you explain why you expect the Allow header to behave the way that you described?
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: Alexandre-Carbenay
I was hoping to be able to use the Allow header in a HATEOAS API context, to retrieve the HTTP methods allowed for a given user, when trying to follow a resource link.
As I can read from the RFC 7231, The actual set of allowed methods is defined by the origin server at the time of each request., so it may depend on the request and not be the same for all requests.
Do you have any other document mentioning that this header must absolutely contain all headers that are implemented by the origin server, even if they are not actually reachable by the requester?
Comment From: eleftherias
@Alexandre-Carbenay
Consider your example where a POST request to "/hellos" requires the user to be authenticated.
As defined in RFC 7235
The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource.
As defined in RFC 7231
The 405 (Method Not Allowed) status code indicates that the method received in the request-line is known by the origin server but not supported by the target resource.
A POST request to "/hellos" without credentials returns a 401 Unauthorized, not a 405 Method Not Allowed .
In line with that, a POST request is supported by the target resource and defined by the origin server at the time of the request, which is why it is included in the Allow header.
From RFC 7231 in the same section that you referenced
The purpose of this field (Allow header) is strictly to inform the recipient of valid request methods associated with the resource.
In this case the resource is "/hellos" and POST is a valid request method.
The purpose of the Allow header is independent of authorization rules.
Comment From: Alexandre-Carbenay
@eleftherias You are right, I will try to find another solution to provide the information to the API consumer about the methods he can use based on its authentication Thanks for clarification, I close this issue