Spring OAuth2 : tokenInfoUri generates ClassCastException with RFC 7662 endpoint - spring-security-oauth2

I'm using Spring Security OAuth2 with tokenInfoUri pointing to a CXF RFC 7662 endpoint implementation.
When calling the tokenInfoUri, Spring generates a
java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Collection
The response from RFC 7662 is :
{
"active":true,
"client_id":"83EQEL8D1OiCIw",
"username":"alice",
"token_type":"Bearer",
"scope":"openid hello.say",
"iat":1470083268,
"exp":1470086868
}
So, scope is deserialized into a String not a Collection.
Spring doesn't seem to handle this RFC (https://www.rfc-editor.org/rfc/rfc7662#section-2.2).
Last version of DefaultAccessTokenConverter handle String type but it should split the scope String (space separator) to create a Set for RFC7662 compliance.
See https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultAccessTokenConverter.java#L154.
Should I create an issue ?
Thanks,
Adrian
Here are the full details ;
Spring Security OAuth 2.0.9.
Stacktrace :
java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Collection
at org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter.extractAuthentication(DefaultAccessTokenConverter.java:124) ~[spring-security-oauth2-2.0.9.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.token.RemoteTokenServices.loadAuthentication(RemoteTokenServices.java:115) ~[spring-security-oauth2-2.0.9.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager.authenticate(OAuth2AuthenticationManager.java:83) ~[spring-security-oauth2-2.0.9.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:150) ~[spring-security-oauth2-2.0.9.RELEASE.jar:na]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) ~[spring-security-web-4.0.4.RELEASE.jar:4.0.4.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120) ~[spring-security-web-4.0.4.RELEASE.jar:4.0.4.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) ~[spring-security-web-4.0.4.RELEASE.jar:4.0.4.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) ~[spring-security-web-4.0.4.RELEASE.jar:4.0.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) ~[spring-security-web-4.0.4.RELEASE.jar:4.0.4.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91) ~[spring-security-web-4.0.4.RELEASE.jar:4.0.4.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) ~[spring-security-web-4.0.4.RELEASE.jar:4.0.4.RELEASE]
Configuration :
security:
user:
password: user
oauth2:
client:
clientId: blabli
clientSecret: blabla
resource:
serviceId: ${PREFIX:}resource
tokenInfoUri: http://localhost:9081/oidc/oauth2/introspect
Request :
POST /oidc/oauth2/introspect HTTP/1.1
Accept: application/json, application/*+json
Authorization: Basic ODNFUUVMOEQxT2lDSXc6dy1OZHpERnlJaTJadThQUkRmeE9Xdw==
Content-Type: application/x-www-form-urlencoded
User-Agent: Java/1.8.0_91
Host: localhost:9080
Connection: keep-alive
Content-Length: 38
token=faa395452928f5126fc8cf61b66bf0f4
Response :
{
"active":true,
"client_id":"83EQEL8D1OiCIw",
"username":"alice",
"token_type":"Bearer",
"scope":"openid hello.say",
"iat":1470083268,
"exp":1470086868
}

This is fixed in Spring OAuth 2.0.10.

Related

CouchDB request with JWT causes error "No DB shards could be opened"

I have a couchdb server, which at this moment is for development and it has just one node running in docker.
I would like to authenticate through JWT. I have build my token.
GET https://comp010:6984/_session
Accept: application/json
Content-Type: application/json; charset=utf-8
Authorization: Bearer <JWT token>
I get proper answer (or at least I think so):
{
"ok": true,
"userCtx": {
"name": "uaru",
"roles": "admin"
},
"info": {
"authentication_handlers": [
"jwt",
"cookie",
"default"
],
"authenticated": "jwt"
}
}
When I send request to get actual object from the database
GET https://comp010:6984/db_userspaces/xxxx3
Accept: application/json
Content-Type: application/json; charset=utf-8
I get "unauthorized" exception. This is ok, I did not authenticated this request. So I add the same authorization header:
GET https://comp010:6984/db_userspaces/xxxx3
Accept: application/json
Content-Type: application/json; charset=utf-8
Authorization: Bearer <JWT token>
And I get
{
"error": "internal_server_error",
"reason": "No DB shards could be opened.",
"ref": 179462285
}
But if I switch off the authorization ( [chttpd] require_valid_user = false), and send the same request without Authorization header,
GET https://comp010:6984/db_userspaces/xxxx3
Accept: application/json
Content-Type: application/json; charset=utf-8
I get proper response.
Server: CouchDB/3.2.1 (Erlang OTP/23)
X-Couch-Request-ID: 02c628ce15
X-CouchDB-Body-Time: 0
{
"_id": "xxxx3",
"_rev": "1-a11f390ffa77a03c557ffbbc7c5fda75",
"x": "1"
}
How JWT can relate to shards? I am puzzled and I cannot find anything related.
There are no errors with Fauxton.
Thank you in advance for any suggestions.
Here is the log when the request took place
couchdb-server_1 | [error] 2022-03-09T04:52:34.662593Z nonode#nohost <0.6234.1> 82a6b79f38 rexi_server: from: nonode#nohost(<0.6134.1>) mfa: fabric_rpc:open_shard/2 error:function_clause [{lists,usort,[<<"admin">>],[{file,"lists.erl"},{line,1063}]},{couch_db,check_security,3,[{file,"src/couch_db.erl"},{line,713}]},{couch_db,is_authorized,2,[{file,"src/couch_db.erl"},{line,705}]},{couch_db,is_member,1,[{file,"src/couch_db.erl"},{line,685}]},{couch_db,check_is_member,1,[{file,"src/couch_db.erl"},{line,671}]},{couch_db,open,2,[{file,"src/couch_db.erl"},{line,166}]},{mem3_util,get_or_create_db,2,[{file,"src/mem3_util.erl"},{line,549}]},{fabric_rpc,open_shard,2,[{file,"src/fabric_rpc.erl"},{line,307}]}]
couchdb-server_1 | [error] 2022-03-09T04:52:34.662982Z nonode#nohost <0.6236.1> 82a6b79f38 rexi_server: from: nonode#nohost(<0.6134.1>) mfa: fabric_rpc:open_shard/2 error:function_clause [{lists,usort,[<<"admin">>],[{file,"lists.erl"},{line,1063}]},{couch_db,check_security,3,[{file,"src/couch_db.erl"},{line,713}]},{couch_db,is_authorized,2,[{file,"src/couch_db.erl"},{line,705}]},{couch_db,is_member,1,[{file,"src/couch_db.erl"},{line,685}]},{couch_db,check_is_member,1,[{file,"src/couch_db.erl"},{line,671}]},{couch_db,open,2,[{file,"src/couch_db.erl"},{line,166}]},{mem3_util,get_or_create_db,2,[{file,"src/mem3_util.erl"},{line,549}]},{fabric_rpc,open_shard,2,[{file,"src/fabric_rpc.erl"},{line,307}]}]
couchdb-server_1 | [error] 2022-03-09T04:52:34.663440Z nonode#nohost <0.6134.1> 82a6b79f38 req_err(179462285) internal_server_error : No DB shards could be opened.
couchdb-server_1 | [<<"fabric_util:get_shard/4 L118">>,<<"fabric_util:get_shard/4 L132">>,<<"fabric:get_security/2 L183">>,<<"chttpd_auth_request:db_authorization_check/1 L112">>,<<"chttpd_auth_request:authorize_request/1 L19">>,<<"chttpd:handle_req_after_auth/2 L325">>,<<"chttpd:process_request/1 L310">>,<<"chttpd:handle_request_int/1 L249">>]
couchdb-server_1 | [notice] 2022-03-09T04:52:34.663753Z nonode#nohost <0.6134.1> 82a6b79f38 comp010:6984 ::ffff:150.26.121.46 uaru GET /db_userspaces/xxxx3 500 ok 2
In the payload to be turned into JWT, roles MUST BE an array.
{
:sub => username,
:'_couchdb.roles' => roles,
:exp => ...,
}
In my case, roles was not. But it means that should be error 400 Bad Request.
The whole problem has nothing to do with shards configuration, etc. The error message was misleading.
Thanks to people in CouchDb slack channel for guiding me in the right direction.

ASP.NET Google Signin: The incoming message has an unexpected message format 'Raw'

I'm trying to implement Google Signin using this page: https://developers.google.com/identity/sign-in/web/backend-auth
Where my token validation call is:
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://www.example.com/api/gtokensignin');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function () {
console.log('Signed in as: ' + xhr.responseText);
};
xhr.send('idtoken=' + id_token);
I inspected the request via the [General] tab in Chrome developer console:
General
Request URL: https://www.example.com/api/gtokensignin
Request Method: POST
Status Code: 400
Remote Address: 192.168.178.219:443
Referrer Policy: strict-origin-when-cross-origin
Response headers
cache-control: private
content-length: 2903
content-type: text/html
date: Thu, 01 Jul 2021 13:23:35 GMT
server: Microsoft-IIS/10.0
x-aspnet-version: 4.0.30319
x-powered-by: ASP.NET
Request headers
:authority: www.example.com
:method: POST
:path: /api/gtokensignin
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
content-length: 1220
content-type: application/x-www-form-urlencoded
cookie: ASP.NET_SessionId=ptesmo1fxwfcgv2cple6xdzi; G_ENABLED_IDPS=google; G_AUTHUSER_H=0; _ga=GA1.1.1295181445.1624434076; __gads=ID=a5e2262ee1a99a43-23e99f1715c900bb:T=1624434076:RT=1624434076:S=ALNI_MZMMJEkUKSKcUUh9w9uH8_Z84lLAQ; _ga_MLNSQWJ4J5=GS1.1.1625123053.36.0.1625123053.0
dnt: 1
origin: https://www.example.com
referer: https://www.example.com/test2.aspx
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
sec-ch-ua-mobile: ?0
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: same-origin
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36
Form data
idtoken: eyJhbGciOiJSUzI2NiIsImtpZCI6IjExMmU0YjUyYWI4MzMwMTdkMzg1Y2UwZDBiNGM2MDU4N2VkMjU4NDIiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXpwIjoiOTU1MjU1MDgxOTEwLWpkcWticDQzNWo1azBnampvZGYzNmZuODEzODZ2ZnFzLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiYXVkIjoiOTU1MjU1MDgxOTEwLWpkcWticDQzNWo1azBnampvZGYzNmZuODEzODZ2ZnFzLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTE3NzYzNjQ1MjYxMDUxNjAzODgxIiwiZW1haWwiOiJmbG9yYW5mZWxlbkBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXRfaGFzaCI6ImdEM0pQc3EyVnJLZlZNenAzbkpJYWciLCJuYW1lIjoiRmxvcmFuIEZlbGVuIiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hL0FBVFhBSnhFMzdPMlJFRjJfLVozeVVZV1A2c1Z1Ylcta2I2TGgzSGNZWEpINnc9czk2LWMiLCJnaXZlbl9uYW1lIjoiRmxvcmFuIiwiZmFtaWx5X25hbWUiOiJGZWxlbiIsImxvY2FsZSI6ImVuIiwiaWF0IjoxNjI1MTY3MjM4LCJleHAiOjE2MjUxNzA4MzgsImp0aSI6ImMwMjgxYWE0YTE1NTBiZWY1ZDJlOTZhOWQwY2Y5ZTU1NTY1MjA1NGEifQ.S_ubEh_4IYhQTPVSye0-tma7pfhAu9xLOoKG5SoO08ZXhqpRxcvJu5C1E6luL9I-LYVLhUNHmplmtR0JJmg47x2lqFH_vwEEGmbhfdEBrEoCXShktxbfLu1p9WcK6MUFMZFT0q93Zp2PgPIfXp_caqqxMeAGEZfzWMK9ZmZhMfmTX_Ny2KlO4KJHR-FvY9Rv1XrcTrTiWfTclKFqpIvyWaUR-wk4srWpu1-riH5J9lz-VC-nmQAbWZw0kxD2DK0RjqsbeXJvPrrtjiCURM-s2b4tfvtyADRkgF2Nh9oOlsMJZRxKXoGNYsLoR0iYYcGbQm4NZGzVwmPj3pxtf1htEA
However, the server returns the following error:
The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml'; 'Json'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details.
Full error:
The server encountered an error processing the request. Please see the service help page for constructing valid requests to the service. The exception message is 'The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml'; 'Json'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details.'. See server logs for more details. The exception stack trace is:
at System.ServiceModel.Dispatcher.DemultiplexingDispatchMessageFormatter.DeserializeRequest(Message message, Object[] parameters)
at System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter.DeserializeRequest(Message message, Object[] parameters)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
Iapi.vb
<OperationContract()>
<Web.WebInvoke(Method:="POST", ResponseFormat:=Web.WebMessageFormat.Json, BodyStyle:=Web.WebMessageBodyStyle.Bare,
UriTemplate:="gtokensignin")>
Function gtokensignin(ByVal str As String) As Stream
I initially had BodyStyle:=Web.WebMessageBodyStyle.WrappedRequest in the above code.
I also tried in OperationContract() to change the BodyStyle= to BodyStyle=WebMessageBodyStyle.Wrapped, but that throws the same error.
I also tried changing the signature to:
<Web.WebInvoke(Method:="POST", RequestFormat = WebMessageFormat.Json, ResponseFormat:=Web.WebMessageFormat.Json, BodyStyle:=Web.WebMessageBodyStyle.Bare,
But then I get the error
'RequestFormat' is not declared. It may be inaccessible due to its protection level.
web.config
<services>
<service behaviorConfiguration="ServiceBehaviour" name="Mysite.api">
<endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="Binding" contract="Mysite.Iapi" />
<endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="httpbind" contract="Mysite.Iapi" />
</service>
</services>
When I go to check the resource availability via https://www.example.com/api.svc/help/operations/gtokensignin I see this page:
I already checked:
WCF service error - Incoming message has an unexpected message format 'Raw'. Expected message formats are 'Xml', 'Json'
WCF request: "The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml'; 'Json'"
The expected message formats for the operation are 'Xml', 'Json'
UPDATE 1
I tried posting via JSON instead of a form post, but then I get the error:
The server encountered an error processing the request. Please see the <a rel="help-page" href="https://www.example.com/api.svc/help">service help page</a> for constructing valid requests to the service. The exception message is 'There was an error deserializing the object of type System.String. End element 'root' from namespace '' expected. Found element 'idtoken' from namespace ''.'. See server logs for more details. The exception stack trace is:
at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)
at System.ServiceModel.Dispatcher.SingleBodyParameterDataContractMessageFormatter.ReadObject(Message message)
at System.ServiceModel.Dispatcher.SingleBodyParameterMessageFormatter.DeserializeRequest(Message message, Object[] parameters)
at System.ServiceModel.Dispatcher.DemultiplexingDispatchMessageFormatter.DeserializeRequest(Message message, Object[] parameters)
at System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter.DeserializeRequest(Message message, Object[] parameters)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</p>
Based on server error. It only accepts JSON or XML.
So try sending id_token as JSON like this.
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://www.example.com/api/gtokensignin');
xhr.setRequestHeader('Content-Type', 'application/json'); // because we are sending json
const data = {
"idtoken": id_token,
};
xhr.send(JSON.stringify(data));
if you insist to send data as a form post look at this answer.
https://stackoverflow.com/a/6329148/5964792
UPDATE 1
Based on your update, Your server accepts the JSON request but it can not deserialize it to System.String because you are posting an object. To send a string as JSON try this
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://www.example.com/api/gtokensignin');
xhr.setRequestHeader('Content-Type', 'application/json'); // because we are sending json
xhr.send(JSON.stringify(id_token));

Getting java.net.SocketException: Connection reset, during making http4 call in Apache camel route

I Am getting below exception from target server. I am migrating camel http component to http4 component.
2018-11-27 01:17:34,156 | ERROR | ernal.req.queue] | DefaultErrorHandler | 81 - org.apache.camel.camel-core - 2.16.3 | Failed delivery for (MessageId: ID:ip-172-16-11-197-60068-1543219848548-41:1:1:1:1 on ExchangeId: ID-ip-172-16-11-197-36927-1543219848013-31-14). Exhausted after delivery attempt: 1 caught: java.net.SocketException: Connection reset
HTTP4 Request headers(not working flow) -
POST /GenieWebService/documentgenerator.asmx HTTP/1.1
Connection: Keep-Alive
Content-Length: 28955
Content-Type: text/xml; charset=utf-8
Accept-Encoding: gzip,deflate
Authorization: Basic ZXNidXNlcjpwYXNzd29yZA==
Host: xmz.ab.a.aaa(This is not actual ip)
User-Agent: Apache-HttpClient/4.5.1 (Java/1.7.0_79)
breadcrumbId: ID-ip-abc-ad-ac-abc-36927-15432193242455-7-90
EXTR_SERVICE_URL: http://abs.ab.a.abc/GenieWebService/documentgenerator.xmzx
X-Forwarded-For: 111.93.62.106, 165.225.106.106
X-Forwarded-Port: 80
X-Forwarded-Proto: http
HTTP request headers (Working flow)
POST /GenieWebService/documentgenerator.asmx HTTP/1.1
Content-Length: 66831
Content-Type: text/xml;charset=utf-8
Authorization: Basic ZXNidXNlcjpwYXNzd29yZA==
Cookie: ASP.NET_SessionId=lairgud4nkaledjpuzarfqj0
Host: abc.ab.a.abc
User-Agent: Jakarta Commons-HttpClient/3.1
breadcrumbId: ID-ip-abc-ab-a-abc-34162-1542796372800-25-80
EXTR_SERVICE_URL: http://abs.ab.a.abc/GenieWebService/documentgenerator.asmx
X-Forwarded-For: 112.196.86.34, 165.225.106.89
X-Forwarded-Port: 80
X-Forwarded-Proto: http
As per my understanding issue seems with cookies headers. In http4 request headers i am not able to see cookies header while it is in http headers.
Can someone plz help here what is the issue and if it is with cookies headers then how I can add cookies. I am using spring dsl and apache-camel 2.16.3 version.
You can set a 100ms timeout on the client by specifying http4://foo?httpClient.soTimeout=100. When a timeout occurs it will probably throw an exception that you can handle like so:
onException(IOException.class).to("direct:timeouts");
from("direct:start")
.setHeader(Exchange.HTTP_QUERY,simple("format=json&count=${in.headers.count}"))
.to("http4://www.host.com/someapi?httpClient.soTimeout=100")
.unmarshal().json(JsonLibrary.JACKSON,MyResponseType.class)
.to("bean:SomeBean?method=echo");
from("direct:timeouts").to("...");
I have used httpClient.socketTimeout=180000 and not using bridgeEndpoint option so camel will use http url that i am setting in headers. Below are the my route.
<route>
<from uri="{{document-service.esb.new.document.internal.req.queue.name}}"/>
<convertBodyTo type="javax.xml.transform.dom.DOMSource" charset="utf-8"/>
<process ref="document-serviceHttpUrlResolver"/>
<removeHeaders pattern="CamelHttp*"/>
<removeHeaders pattern="JMS*"/>
<setHeader headerName="SOAPAction">
<xpath resultType="java.lang.String">function:properties('document-service.esb.new_genie.document.service.soap.action')</xpath>
</setHeader>
<setHeader headerName="CamelHttpUri">
<xpath resultType="java.lang.String">in:header('EXTR_SERVICE_URL')</xpath>
</setHeader>
<!--CamelHttpUri value will be - http://xyz.xy.x.bcd/WebGenie/DocumentGenerator.svc-->
<setHeader headerName="Content-Type">
<xpath resultType="java.lang.String">function:properties('http.content.type.value')</xpath>
</setHeader>
<process ref="document-serviceSoapWrapper"/>
<log message="*** A request message sent to New Genie service: ${body}" loggingLevel="INFO" logName="document-service"/>
<to uri="http4://abc.ab.a.abc/GenieWebService/documentgenerator.asmx?httpClient.socketTimeout=180000"/>
<convertBodyTo type="javax.xml.transform.dom.DOMSource" charset="utf-8"/>
<to uri="{{document-service.esb.new.document.internal.resp.queue.name}}{{document-service.esb.internal.queue.parameters}}" pattern="InOnly"/>
</route>

Symfony3 fosrest api method options not allowed

I've got an api build in Symfony 3 with the FOSrestBundle and NelmioCORSBundle.
In my controller i have an method postSaveLotteryAction() which fosrest converts to the route /lotteries/saves/lotteries
Now my ReactJS application uses Axios to make a xhr (ajax) request to the api (that is hosted on a diffrent domain) and because of CORS it first sends out a OPTIONS request.
My apache server is configured correctly with the correct headers as shown below.
The message shown by Symfony is 405 method not allowed. But everything points to the OPTIONS method is allowed.
Access-Control-Allow-Headers: x-requested-with, Content-Type, origin, authorization, accept, client-security-token
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 1000
Allow:
Connection: Keep-Alive
Content-Length: 250
Content-Type: text/html; charset=iso-8859-1
Date: Wed, 11 Apr 2018 07:03:30 GMT
Keep-Alive: timeout=2, max=100
Server: Apache/2
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: nl-NL,nl;q=0.9,en-US;q=0.8,en;q=0.7
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Connection: keep-alive
Host: api.naamloting.nl
Origin: http://beta.naamloting.nl
This is my bin/console d:r output where i've added in the route.yml the GET, OPTIONS, POST methods.
get_lottery GET|POST|OPTIONS ANY ANY /lotteries/{uuid}
get_lottery_stats GET|POST|OPTIONS ANY ANY /lottery/stats
post_lottery_save_lottery GET|POST|OPTIONS ANY ANY /lotteries/saves/lotteries
get_lottery_image GET|POST|OPTIONS ANY ANY /lotteries/{nameOfWinner}/image
get_lottery_ticket GET|POST|OPTIONS ANY ANY /lotteries/{nameOfWinner}/ticket
Also here is my config.yml (partially) so it's clearer to see what maybe causes it.
# Nelmio CORS
nelmio_cors:
defaults:
allow_origin: ['*']
allow_methods: ["POST", "PUT", "GET", "DELETE", "OPTIONS"]
allow_headers: ["content-type"]
max_age: 3600
paths:
'^/lottery': ~
'^/lotteries': ~
# FOS REST Bundle
fos_rest:
body_listener: true
param_fetcher_listener: true
view:
view_response_listener: 'force'
formats:
jsonp: true
json: true
xml: false
rss: false
mime_types:
json: ['application/json', 'application/x-json']
jpg: 'image/jpeg'
png: 'image/png'
jsonp_handler: ~
routing_loader:
default_format: json
include_format: false
format_listener:
rules:
- { path: ^/, priorities: [ json, jsonp ], fallback_format: ~, prefer_extension: true }
exception:
enabled: true
exception_controller: 'fos_rest.exception.controller:showAction'
SOLVED
Looking at the error page it seems to me that Symfony was not the problem and i was correct.
Apache was the troublemaker that didn't allow the OPTIONS method so it always returned an 405 not allowed.
I added the method type and the request is handled correctly.
It seems that sometimes there could be happening a "preflight" OPTIONS request with the real required method in the HEADER.
I see that you allow "PUT" method in nelmio, but not in routes. Try allowing PUT in routes and see if that fixes the problem.
More info:
https://www.html5rocks.com/en/tutorials/cors/

WebApi POST body not binding with FromBody

I've defined my ApiController's method like so:
public HttpResponseMessage Post([FromBody] string json)
The method is being called, but json is always null. I can see via Fiddler that what I'm passing is what I expect (hostname obviously edited out). What am I missing here?
POST http://somehost.com/api/somemethod HTTP/1.1
User-Agent: Fiddler
Host: somehost.com
Content-Length: 54
Content-Type: application/json
{"site":"home","region":"region","flags":"flags"}

Resources