0

I know this is an old question, and I have read many articles about it and finally reached here. Every thing works fine without authentication (without the [System.Web.Mvc.Authorize]):

  1. The api controller:

    using System.Web.Http;
    using System.Web.Mvc;
    
    namespace WebApi.Controllers
    {
        [System.Web.Mvc.Authorize]
        public class ProductsController : ApiController
        {
            public IEnumerable<string> GetAllNames()
            {
                return new List<string> {"abc", "def", User.Identity.Name};
            }
    
            public string GetName(string name)
            {
                return name;
            }
        }
    }
    
  2. Web.Config The four lines under are added to support CORS.

      <system.webServer>
        <validation validateIntegratedModeConfiguration="false" />
        <modules>
          <remove name="WebDAVModule"/><!-- ADD THIS to enable POST/DELETE -->
        </modules>
        <handlers>
          <remove name="WebDAV" /><!-- ADD THIS to enable POST/DELETE -->
          <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
          <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
          <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
          <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
          <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
          <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
        </handlers>
        <httpProtocol>
          <customHeaders>
            <clear />
            <!-- Adding the following custom HttpHeaders will help prevent CORS from stopping the Request-->
            <add name="Access-Control-Allow-Origin" value="*" />
            <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
          </customHeaders>
        </httpProtocol>
      </system.webServer>
    

But when the [Authorize] is added to the api controller, everything goes wrong.

Here is the the page call the api, there are up to 7 solutions that I read from the web, would be a textbook, if any of them worked. Many people said "it works for me", but none for me.

I commented all the solutions under the title, and recorded the error it caused.

        var host = 'http://localhost:54364/api/products/';
        userName = "[email protected]";
        password = "password";
        $(document).ready(function () {
            //Solution 1: OPTIONS http://localhost:54364/api/products/GetAllNames?name=someone 405 (Method Not Allowed) / http://localhost:54364/api/products/GetAllNames?name=someone. Invalid HTTP status code 405  
            //$.ajaxSetup({
            //    headers: {
            //        'Authorization': "Basic " + btoa("[email protected]" + ":" + "nodenode")
            //    }
            //});
            $.ajax({
                type: "GET",
                url: host + "GetAllNames",
                dataType: 'json',
                //Solution 2: Ok, but User.Identity.UserName returns "", an empty string; I think it does not work at all.
                //username: userName,
                //password: password,
                async: false,
                //Solution 3: GET http://localhost:54364/api/products/GetAllNames?name=someone 405 (Method Not Allowed) / OPTIONS http://localhost:54364/api/products/GetAllNames?name=someone 405 (Method Not Allowed) / XMLHttpRequest cannot load http://localhost:54364/api/products/GetAllNames?name=someone. Invalid HTTP status code 405
                //headers: { "Authorization": btoa("Basic " + userName + ":" + password) },
                //Solution 4: XMLHttpRequest cannot load http://localhost:54364/api/products/GetAllNames. Wildcards cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost:64710' is therefore not allowed access.
                //xhrFields: {
                //    withCredentials: true
                //},
                beforeSend: function (xhr) {
                    //Solution 5: Same with solution 2.
                    //xhr.withCredentials = true;
                    //Solution 6: OPTIONS http://localhost:54364/api/products/GetAllNames?name=someone 405 (Method Not Allowed) / OPTIONS http://localhost:54364/api/products/GetAllNames?name=someone 405 (Method Not Allowed)  / XMLHttpRequest cannot load http://localhost:54364/api/products/GetAllNames?name=someone. Invalid HTTP status code 405 
                    //xhr.setRequestHeader("Authorization", "Basic " + btoa(userName + ":" + password));
                    //Solution 7 ( 5 + 6 ): same with solution 6.
                },
                crossDomain: true,
                success:
                    function(data) {
                        // On success, 'data' contains a list of products.
                        $.each(data, function(key, item) {
                            // Add a list item for the product.
                            $('<li>', { text: formatItem(item) }).appendTo($('#ajax'));
                        });
                    }
            });

Being new with ajax and web api (just 2 days experience), I think I might missed something, for example, solution 4 has no username/password information, how could it work?

Thanks in advance, and any comments will be welcome.

1 Answer 1

1

Problem is in Access-Control-Allow-Origin header of your response. If you are using authentication, then you can't use wildcard *. You need to explicitly set the domain.

And if you want to use withCredentials: true then your server must set an extra header Access-Control-Allow-Credentials as true

Access-Control-Allow-Credentials: true
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your answer. Since I'm not working on this testing now, I will give my feedback of what happens later :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.