Definition
Find a good description for CORS (Cross-Origin Resource Sharing) at this link: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
Learn more about CORS here: https://youtube.com/watch?v=Ka8vG5miErk
Enabling CORS
To enable CORS on IIS - all sites on the machine:
Add a or change web.config on the root website (Default Web site):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<cors enabled="true" failUnlistedOrigins="true">
<add origin="*"/>
<add origin="https://www.test-cors.org" allowCredentials="true" >
<allowHeaders allowAllRequestedHeaders="true"/>
</add>
</cors>
</system.webServer>
</configuration>To do this on App level - change Web.config in the same way - but beware that web-config is part of the installation and will be replaced upon update.
Details from the IIS team on how to configure CORS using XML (like above):
To test that CORS is active, you can use this online tool, for example, https://www.test-cors.org/.
Just enter the root URL of your site in "Remote URL".
Contender Implementation - Cors With Dynamic Decisions
To allow dynamic decisions on whom to allow Cors entry, you can now implement this model pattern:
Class named TK_WebCors with a static method GetAllowOrigin(org:String):Boolean
This method will be called when you use RestAllowed Viewmodels and the caller's Origin in small caps will be given in the parameter.
This example returns true for all -> which means that all origins are ok.
A more realistic implementation might be:
MyValidCorsCallers.allinstances->select(x|x.Origin=org)->first.Allowed
The check is cached in an internal Dictionary for 10 minutes - changes will be discovered in 10-minute intervals.
If the model pattern is wrong, you get an exception in the Turnkey log:
CentralLogging("CheckCorsHeaders - check model pattern static TK_WebCors.GetAllowOrigin(vOrigin):string", ex)
NOTE - if you have Cors-middleware in IIS or Cassini, you will not see the effect from the above since middleware will overwrite.
If Cors headers are applied, this is what we apply:
Response.Headers.Add("Access-Control-Allow-Origin", cleanorg);
Response.Headers.Add("Access-Control-Allow-Credentials", "true");
Response.Headers.Add("Access-Control-Allow-Headers", "authorization");
Response.Headers.Add("Access-Control-Allow-Methods", "POST, GET");
Response.Headers.Add("Vary", "Origin");
You may also send (not recommended due to the open nature of the web) the credentials in the basic authentication scheme:
function myFunction(){
$.ajax({
type: "get",
url: "http://localhost:5052/TurnkeyRest/Get?command=AutoFormClass1x&id=1!45",
xhrFields: { withCredentials: true },
headers: {
"Authorization": "Basic " + btoa("theuser:thepwd")
}
}).done(function (data) {
debugger;
$('#value1').text(data);
}).fail(function (jqXHR, textStatus, errorThrown) {
debugger;
$('#value1').text(jqXHR.responseText || textStatus);
});
}
Writing to ViewModels from Javascript
Post data to a ViewModel-driven MDriven Form (i.e., not the best way - but rather injecting data into standard UI) - you can proceed like this:
let formData = new FormData();
formData.append("Filter", "v");
fetch('https://YOURTURNKEYSITE/TurnkeyRest/Post?command=AutoFormSysUserSeeker', {
headers: new Headers(),
method: "POST",
mode: 'cors',
body: formData
}).then((response) => {
if (response.ok) {
return response.json()
} else {
//
}
}).then((responseJsonData) => {
callback && callback(responseJsonData);
}).catch((error) => {
console.log("getWatchHistory error " + error);
});
