CORS protocol in explicit web proxy when using session-based, cookie-enabled, and captive portal-enabled SAML authentication
The FortiGate explicit web proxy supports the Cross-Origin Resource Sharing (CORS) protocol, which allows the FortiGate to process a CORS preflight request and an actual CORS request properly, in addition to a simple CORS request when using session-based, cookie-enabled, and captive portal-enabled SAML authentication. This allows a FortiGate explicit web proxy user with this specific configuration to properly view a web page requiring CORS with domains embedded in it other than its own domain.
To configure the FortiGate:
- Configure the authentication rule:
config authentication rule edit "saml" set srcaddr "all" set ip-based disable set active-auth-method "saml" set web-auth-cookie enable next end
- Configure the captive portal:
config authentication setting set captive-portal "fgt9.myqalab.local" end
- Configure the proxy policy
config firewall proxy-policy edit 3 set proxy explicit-web set dstintf "port9" set srcaddr "all" set dstaddr "all" set service "webproxy" set action accept set schedule "always" set logtraffic all set groups "ldap-group-saml" set utm-status enable set profile-protocol-options "protocol" set ssl-ssh-profile "deep-custom" set av-profile "av" set application-list "fff" next end
CORS request scenarios
Preflight CORS request
The client sends the initial CORS preflight request (OPTIONS
with the origin header) to the web server through FortiGate's web proxy and receives a CORS 200 OK
response (with headers, such as Access-Control-Allow-Origin
). The FortiGate will not redirect the client to the captive capital for authentication:
> OPTIONS /bidRequest HTTP/1.1 > Host: c2shb.pubgw.yahoo.com > User-Agent: curl/7.61.1 > Accept: */* > Access-Control-Request-Method: GET > Access-Control-Request-Headers: content-type,x-openrtb-version > Origin: https://www.cnn.com ... < HTTP/1.1 200 OK < Date: Thu, 19 May 2022 01:49:17 GMT < Content-Length: 0 < Server: ATS/9.1.0.46 < Access-Control-Allow-Origin: https://www.cnn.com < Access-Control-Allow-Methods: GET,POST,OPTIONS < Access-Control-Allow-Headers: X-Requested-With,Content-Type,X-Openrtb-Version < Access-Control-Allow-Credentials: true < Access-Control-Max-Age: 600 < Age: 0 < Connection: keep-alive < Set-Cookie: A3=d=AQABBB2ihWICEIUyD_Du5ol8tMdKKWxspR8FEgEBAQHzhmKPYgAAAAAA_eMAAA&S=AQAAAlU0dAheQx6euvcPs8ErK4I; Expires=Fri, 19 May 2023 07:49:17 GMT; Max-Age=31557600; Domain=.yahoo.com; Path=/; SameSite=None; Secure; HttpOnly
Real CORS request
Once the initial preflight request for the client is successful, the client sends the real CORS request (GET
request with origin header) to the FortiGate, The FortiGate then replies with a 30x response to redirect the client to the captive portal. The 30x response includes CORS headers such as Access-Control-Allow-Origin
:
> GET /bidRequest HTTP/1.1 > Host: c2shb.pubgw.yahoo.com > User-Agent: curl/7.61.1 > Accept: */* > Origin: https://www.cnn.com ... < HTTP/1.1 303 See Other < Access-Control-Max-Age: 1 < Access-Control-Allow-Origin: https://www.cnn.com < Access-Control-Allow-Credentials: true < Set-Cookie: FTNT-EP-FG900D3915800054=pqWlpdswdcCnpaWli6WlpcjEwszGmJbGksbBwMCVwcPBlpKRnMGTl52QxJeUwYPW18aYlJWLlIuUlZWLlJalpQ==; Path=/; Domain=.pubgw.yahoo.com; HttpOnly; SameSite=None; Secure < Connection: close < Content-Type: text/html < Cache-Control: no-cache < Location: https://fgt9.myqalab.local:7831/test/saml/login/?cptype=ckauth&scheme=https&4Tmthd=0&host=c2shb.pubgw.yahoo.com&port=443&rule=98&uri=L2JpZFJlcXVlc3Q=&cdata=pqWlpdswdcCnpaWli6WlpcjEwszGmJbGksbBwMCVwcPBlpKRnMGTl52QxJeUwYPW18aYlJWLlIuUlZWLlJalpQ== < Content-Length: 0
Redirection to captive portal
Once the client's real CORS request is redirected to the captive portal, the client senda another preflight to the captive portal. The captive portal then replies with a 20x response, which includes CORS headers such as Access-Control-Allow-Origin
:
> OPTIONS /test/saml/login/?cptype=ckauth&scheme=https&4Tmthd=1&host=gql.reddit.com&port=443&rule=98&uri=Lw==&cdata=pqWlpQM5dcCnpaWliqWlpcjEwszGmJbGksbAk5WTl8aTwJDGnJ2Tl52QxpHDkYPW18aYlJWLlIuUlZWLlJGWpQ== HTTP/1.1 > Host: fgt9.myqalab.local:7831 > Connection: keep-alive > Accept: */* > Access-Control-Request-Method: GET > Access-Control-Request-Headers: authorization,content-type,x-reddit-compression,x-reddit-loid,x-reddit-session > Origin: null > User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36 Edg/100.0.1185.36 > Sec-Fetch-Mode: cors > Sec-Fetch-Site: cross-site > Sec-Fetch-Dest: empty > Referer: https://www.reddit.com/ > Accept-Encoding: gzip, deflate, br > Accept-Language: en-US,en;q=0.9 ... < HTTP/1.1 204 No Content < Access-Control-Max-Age: 86400 < Access-Control-Allow-Methods: GET < Access-Control-Allow-Headers: authorization,content-type,x-reddit-compression,x-reddit-loid,x-reddit-session < Access-Control-Allow-Origin: null < Access-Control-Allow-Credentials: true
Simple CORS request
If a simple CORS request (no preflight request sent before it) is used, when the FortiGate receives the simple request, it replies with a 30x response that includes CORS headers, such as Access-Control-Allow-Origin
:
> Host: www.yahoo.com > User-Agent: curl/7.61.1 > Accept: */* > Origin: https://www.cnn.com ... < HTTP/1.1 303 See Other < Access-Control-Max-Age: 1 < Access-Control-Allow-Origin: https://www.cnn.com < Access-Control-Allow-Credentials: true < Set-Cookie: FTNT-EP-FG900D3915800000=pqWlpaw7dcCnpaWli6WlpcjEwszGmJbGksbAkpOcxMDDlpbGlMSTl52QwcGcl4PW18aYlJWLlIuUlZWLlJalpQ==; Path=/; Domain=.yahoo.com; HttpOnly; SameSite=None; Secure < Connection: close < Content-Type: text/html < Cache-Control: no-cache < Location: https://fgt9.myqalab.local:7831/test/saml/login/?cptype=ckauth&scheme=https&4Tmthd=0&host=www.yahoo.com&port=443&rule=98&uri=Lw==&cdata=pqWlpaw7dcCnpaWli6WlpcjEwszGmJbGksbAkpOcxMDDlpbGlMSTl52QwcGcl4PW18aYlJWLlIuUlZWLlJalpQ== < Content-Length: 0