05-20-2020 02:40 AM - edited 05-20-2020 02:46 AM
Hi Guys,
I found the problem while developing web front-end with javascript to make a request to NSO northbound API.
Due to CORS(Cross-Origin Resource Sharing) mechanism browser will sent a preflight request to NSO before the main request.
So, In NCS version 5.2 it working fine by adding CORS header in ncs.conf under <restconf>, But after changed the version from 5.2 TO 5.3 (with same ncs.conf). It seem like NSO northbound API reply back 401 Unauthorized to the preflight request.
I also tried to debug it with packet capture and here is the capture.
this tcpstream i got in version 5.3:
### this is the response in ncs 5.3 #### <preflight request> OPTIONS /restconf/data/tailf-ncs:devices/device HTTP/1.1 Host: 127.0.0.1:8080 Connection: keep-alive Accept: */* Access-Control-Request-Method: GET Access-Control-Request-Headers: authorization Origin: http://localhost:3000 Sec-Fetch-Mode: cors Sec-Fetch-Site: cross-site Sec-Fetch-Dest: empty Referer: http://localhost:3000/service/new <401 error response> HTTP/1.1 401 Unauthorized Date: Sun, 03 May 2020 13:43:34 GMT Content-Length: 169 Content-Type: application/yang-data+xml WWW-Authenticate: Basic realm="restconf" Content-Security-Policy: default-src 'self'; block-all-mixed-content; base-uri 'self'; frame-ancestors 'none'; Strict-Transport-Security: max-age=15552000; includeSubDomains X-Content-Type-Options: nosniff X-Frame-Options: DENY X-XSS-Protection: 1; mode=block <errors xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf"> <error> <error-tag>access-denied</error-tag> <error-type>protocol</error-type> </error> </errors>
As i'm understanding broswer will not send any Authorization/Credential in the preflight request header by default.
NOTE : I tried to request it manually by postman, it working fine and got CORS header back in the response.
compare to the mechanism in ncs 5.2 :
### this is the response in ncs 5.2 #### <preflight request> OPTIONS /restconf/data/tailf-ncs:devices/device HTTP/1.1 Host: 127.0.0.1:8080 Connection: keep-alive Accept: */* Access-Control-Request-Method: GET Access-Control-Request-Headers: authorization Origin: http://localhost:3000 Sec-Fetch-Mode: cors Sec-Fetch-Site: cross-site ....<snippet output> <respose with cors header permission> HTTP/1.1 200 OK Date: Sun, 03 May 2020 13:29:46 GMT Allow: DELETE, GET, HEAD, PATCH, POST, PUT, OPTIONS Cache-Control: private, no-cache, must-revalidate, proxy-revalidate Content-Length: 0 Content-Type: text/html Accept-Patch: application/yang-data+xml, application/yang-data+json Access-Control-Allow-Headers: Accept, Content-Type, Authorization, Accept-Encoding, Host, Origin, Content-Encoding, X-PING, X-PINGOTHER Access-Control-Allow-Credentials: true Access-Control-Allow-Methods: GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS Access-Control-Allow-Origin: * ....<snippet output> <actual request with Authorization> GET /restconf/data/tailf-ncs:devices/device HTTP/1.1 Host: 127.0.0.1:8080 Connection: keep-alive Accept: application/yang-data+json Authorization: Basic YWRtaW46YWRtaW4= User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36 Origin: http://localhost:3000 Sec-Fetch-Site: cross-site Sec-Fetch-Mode: cors Sec-Fetch-Dest: empty Referer: http://localhost:3000/service/new ....<snippet output> <response> HTTP/1.1 200 OK Date: Sun, 03 May 2020 13:29:46 GMT Last-Modified: Fri, 13 Mar 2020 04:00:54 GMT Cache-Control: private, no-cache, must-revalidate, proxy-revalidate Etag: "1584-43963-840187" Content-Type: application/yang-data+json Transfer-Encoding: chunked Access-Control-Allow-Headers: Accept, Content-Type, Authorization, Accept-Encoding, Host, Origin, Content-Encoding, X-PING, X-PINGOTHER Access-Control-Allow-Credentials: true Access-Control-Allow-Methods: GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS Access-Control-Allow-Origin: * Pragma: no-cache 100F { "tailf-ncs:device": [ { "name": "acc1", "address": "127.0.0.1", "port": 10026, "ssh": { "host-key": [ { ....<snippet output>
I also implement an workaround by creating nginx-reverse-proxy to handle the preflight request.
But my question is what the best solution without reverse-proxy in the middle or do i miss any additional configuration to make it working ?
Thank you so much :)
Here is config i'm using :
<restconf> <enabled>true</enabled> <custom-headers> <header> <name>Access-Control-Allow-Origin</name> <value>*</value> </header> <header> <name>Access-Control-Allow-Methods</name> <value>GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS</value> </header> <header> <name>Access-Control-Allow-Credentials</name> <value>true</value> </header> <header> <name>Access-Control-Allow-Headers</name> <value>Accept, Content-Type, Authorization, Accept-Encoding, Host, Origin, Content-Encoding, X-PING, X-PINGOTHER</value> </header> </custom-headers> </restconf>
Solved! Go to Solution.
05-20-2020 05:34 AM
05-20-2020 05:34 AM
05-20-2020 05:40 AM
05-20-2020 07:07 AM
Thanks for the explanation. It makes sense for disabled it because of the security concerns.
I have tried to set withCredentials flag before, but it seem to not working in firefox. Anyway I will go with reverse-proxy workaround, support case not needed for now.
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide