Search Unity

WebGL, CORS and XMLHttpRequest.withCredentials

Discussion in 'Web' started by halbpro, Oct 25, 2016.

Thread Status:
Not open for further replies.
  1. halbpro

    halbpro

    Joined:
    Jul 30, 2015
    Posts:
    4
    Hi,

    So we have a WebGL project that's calling out to a third party API. Under the hood I understand that a WebGL Unity Player makes it HTTP calls via XMLHttpRequest, but because we're going cross domain issues arise. We need to use cookie based auth, which means setting up CORS and setting XMLHttpRequest.withCredentials to true.

    We've already got the appropriate CORS headers in place, but setting XMLHttpRequest.withCredentials is more of an issue. Without it the request doesn't succeed, as the session cookie the API is setting doesn't propagate into future requests once it's been set. Is there a way of actually setting the XMLHttpRequest.withCredentials flag when kicking off a request via WWW or UnityWebRequest? Or are we going to be forced into writing a JavaScript plugin to support this? That seems like a rather complex solution to the problem, and something we'd rather avoid.
     
  2. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    327
    Hello halbpro.

    Currently there is no way to perform credentialed request directly from the managed code. Normally you would create a JavaScript plugin to perform such a special task.

    Alternatively, you can try the following quick hack, which simply overrides the XMLHttpRequest creation function and adds withCredentials to all the web requests. Add the following Assets/Plugins/withCredentials.jspre file to your project:
    Code (JavaScript):
    1.   Object.defineProperty(Module, "asmLibraryArg", {
    2.     set: function (value) {
    3.       value._JS_WebRequest_Create = function (url, method) {
    4.         var http = new XMLHttpRequest;
    5.         var _url = Pointer_stringify(url);
    6.         var _method = Pointer_stringify(method);
    7.         http.open(_method, _url, true);
    8.         http.withCredentials = true; // can be also set conditionally depending on the _url variable
    9.         console.log("using credentialed XMLHttpRequest for " + _url);
    10.         http.responseType = "arraybuffer";
    11.         wr.requestInstances[wr.nextRequestId] = http;
    12.         return wr.nextRequestId++;
    13.       }
    14.       Module._asmLibraryArg = value;
    15.     },
    16.     get: function () { return Module._asmLibraryArg; },
    17.   });
    You may as well put this code right after the Module declaration in your index.html. Just note that the latter solution is temporary and version specific, therefore might not work in some versions of Unity (if it doesn't let me know your version).
     
    Last edited: Oct 26, 2016
    savely00 likes this.
  3. stevenyang123

    stevenyang123

    Joined:
    Apr 14, 2017
    Posts:
    1
    hi alexsuvorov:
    I put the above code to my project, but packaged webgle error, can not start, my version is unity 5.3.5, how to deal with this problem
     
  4. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    327
    Hello stevenyang123.

    I believe this should do the trick in 5.3.5 as well. You don't have to put this code into your project or rebuild anything in order to test it. First build your project as usual and make sure it works fine. Then put the mentioned code directly into your index.html right after the Module = {...} declaration. Let me know if your build does not launch anymore after you add this code, and also share the link to your build if possible.
     
  5. TriNityGER

    TriNityGER

    Joined:
    Sep 1, 2017
    Posts:
    29
    I can confirm this hack still works with 2018.3.8f1 when using it as a Plugin.
     
  6. vanmani

    vanmani

    Joined:
    Jul 11, 2012
    Posts:
    6
    This solution no longer appears to work in 2019.1.2...?

    Console reports - Uncaught TypeError: Cannot redefine property: asmLibraryArg
     
  7. miloszcc

    miloszcc

    Joined:
    May 14, 2014
    Posts:
    3
    I have the same problem in 2019.1.14f1 and 2019.2.6f1. I have a .jspre file where I define the "asmLibraryArg" property:

    Code (JavaScript):
    1. Object.defineProperty(Module, "asmLibraryArg", {
    2.     set: function (value) {
    3.       value._JS_WebRequest_Create = function (url, method) {
    4.         var http = new XMLHttpRequest;
    5.         var _url = Pointer_stringify(url);
    6.         var _method = Pointer_stringify(method);
    7.         http.open(_method, _url, true);      
    8.         if (_url.includes("openid/authorize") || _url.includes("v1/auth")) { // using credentialed XMLHttpRequest for obtaining authorization code
    9.             http.withCredentials = true; // can be also set conditionally depending on the _url variable
    10.         }
    11.         http.responseType = "arraybuffer";
    12.         wr.requestInstances[wr.nextRequestId] = http;
    13.         return wr.nextRequestId++;
    14.       }
    15.       Module._asmLibraryArg = value;
    16.     },
    17.     get: function () { return Module._asmLibraryArg; }
    18.   });
    As I can see the generated WebGL code already contains this property:
    Code (JavaScript):
    1. if (Module.CachedXMLHttpRequestDisable !== true) {
    2.                 Object.defineProperty(Module, "asmLibraryArg", {
    3.                     get: (function() {
    4.                         return Module.realAsmLibraryArg
    5.                     }
    6.                     ),
    7.                     set: (function(value) {
    8.                         if (typeof value == "object" && typeof value._JS_WebRequest_Create == "function")
    9.                             value._JS_WebRequest_Create = CachedXMLHttpRequest.wrap(value._JS_WebRequest_Create);
    10.                         Module.realAsmLibraryArg = value
    11.                     }
    12.                     )
    13.                 })
    14.             }
    Do you know how to solve this problem?

    Update 2019-10-30
    The solution to the problem was to remove our function as the function provided by Unity is correct.
     
    Last edited: Oct 30, 2019
    savely00 and kkacperz like this.
  8. carmenfan

    carmenfan

    Joined:
    Apr 27, 2018
    Posts:
    2
    Hi I'm running into the exact problem. Can you (or anyone else who has came across this) clarify how did you solve this?

    If I remove my .jspre then I run into CORS problems as withCredentials is not set.
     
  9. Parsec3d

    Parsec3d

    Joined:
    Apr 2, 2015
    Posts:
    27
    Same problem trying to fetch a live stream from twitch everything works on the editor, but once I upload the webgl to a server I get the CORS error...

    using Unity 2020
     
  10. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    953
    This thread is not about fixing CORS issues, and the presented solution is not about how to fix CORS issues.

    This thread is about how to perform credentialed requests across origins, which are a special form for CORS requests for specific remote server scenarios.

    Are you a web server administrator who has explicitly configured a web server to require credentialed network transfers from cross-origin domains? If yes, then this thread discusses how to enable credentialed requests. See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS under section "Requests with credentials" for more information.

    If not, and you are observing CORS related errors, then it means that the game resources are being hosted across multiple servers/domains, which means that the servers must be configured for cross-origin use. Read through https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS to understand how CORS works across multiple domains.

    This thread is quite old, from 2016, so closing this one out. If you are still experiencing CORS-related issues, please open a new forum thread with a description of your hosting scenario, and preferably a live test link to your game so that others will be able to reproduce the hosting problem you are experiencing. Thanks!
     
Thread Status:
Not open for further replies.