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