title: Accessing ServiceStack Authenticated Service using Ajax
body: <p>I've been working through a simple API example, a modified version of the ServiceStack Hello World example with authentication.  The goal of the proof of concept is to create an a RESTful API that contains services requiring authentication accessible entirely through Ajax from several different web projects.</p>
  
  <p>I've read the wiki for, and implemented, Authentication and authorization and implementing CORS (many, results [sorry, not enough cred to point to the relevant link]).  At this point, my Hello service can authenticate using a custom authentication mechanism which is over-riding CredentialsAuthProvider and a custom user session object.  I've created, or borrowed, rather, a simple test application (an entirely separate project to simulate our needs) and can authenticate and then call into the Hello service, passing a name, and receive a 'Hello Fred' response through a single browser session.  That is, I can call the /auth/credentials path in the url, passing the username and id, and receive a proper response.  I can then update the url to /hello/fred and receive a valid response.  </p>
  
  <p>My breakdown in understanding is how to implement the authentication for all ajax calls.  My initial login, below, works fine.  No matter what I do, my attempt to call the authenticated service via ajax, I either receive a OPTIONS 404 error or Not Found error, or Origin http // localhost:12345 (pseudo-link) is not allowed by Access-Control-Allow-Origin, etc.</p>
  
  <p>Do I need to go <a href="https://stackoverflow.com/questions/17669389/how-can-i-authenticate-with-servicestack-using-jquery-ajax">this route</a>?</p>
  
  <p>Sorry if this is confusing. I can provide greater details if required, but think this might be sufficient help the knowledgeable to help my lack of understanding.</p>
  
  <pre><code>    function InvokeLogin() {
      var Basic = new Object();
      Basic.UserName = "MyUser";
     Basic.password = "MyPass";
  
      $.ajax({
          type: "POST",
          contentType: "application/json; charset=utf-8",
          dataType: "json",
          data: JSON.stringify(Basic),
          url: "http://localhost:58795/auth/credentials",
          success: function (data, textStatus, jqXHR) {
                  alert('Authenticated! Now you can run Hello Service.');
              },
          error: function(xhr, textStatus, errorThrown) {
              var data = $.parseJSON(xhr.responseText);
              if (data === null)
                  alert(textStatus + " HttpCode:" + xhr.status);
              else
                  alert("ERROR: " + data.ResponseStatus.Message + (data.ResponseStatus.StackTrace ? " \r\n Stack:" + data.ResponseStatus.StackTrace : ""));
          }
      });
  }
  </code></pre>
  
  <p><strong>EDIT:</strong></p>
  
  <p>Based on the responses and the link provided by Stefan, I've made a couple of changes:</p>
  
  <p><strong>My Config</strong>  (Note: I'm using custom authentication and session object and that is all working correctly.)</p>
  
  <pre><code>public override void Configure(Funq.Container container)
  {
      Plugins.Add(new AuthFeature(() =&gt; new CustomUserSession(), 
                  new IAuthProvider[] {
                  new CustomCredentialsAuthProvider(),
                      }));
  
      base.SetConfig(new EndpointHostConfig
      {
          GlobalResponseHeaders = {
              { "Access-Control-Allow-Origin", "*" },
              { "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" },
              { "Access-Control-Allow-Headers", "Content-Type, Authorization" },
          },
          DefaultContentType = "application/json"
      });
  
      Plugins.Add(new CorsFeature());
      this.RequestFilters.Add((httpReq, httpRes, requestDto) =&gt;
      {
          //Handles Request and closes Responses after emitting global HTTP Headers
          if (httpReq.HttpMethod == "OPTIONS")
              httpRes.EndRequest();   //   extension method
      });
  
      Routes
          .Add&lt;Hello&gt;("/Hello", "GET, OPTIONS");
  
  
      container.Register&lt;ICacheClient&gt;(new MemoryCacheClient());
      var userRep = new InMemoryAuthRepository();
      container.Register&lt;IUserAuthRepository&gt;(userRep);
  }
  </code></pre>
  
  <p><strong>My Simple Hello Service</strong></p>
  
  <pre><code>[EnableCors]
  public class HelloService : IService
  {
      [Authenticate]
      public object GET(Hello request)
      {
          Looks strange when the name is null so we replace with a generic name.
          var name = request.Name ?? "John Doe";
          return new HelloResponse { Result = "Hello, " + name };
      }
  }
  </code></pre>
  
  <p>After making the login call, above, my subsequent call the Hello service is now yielding a 401 error, which is progress, though not where I need to be.  (The Jquery.support.cors= true is set in my script file.)</p>
  
  <pre><code>function helloService() {
      $.ajax({
          type: "GET",
          contentType: "application/json",
          dataType: "json",
          url: "http://localhost:58795/hello",
          success: function (data, textStatus, jqXHR) {
              alert(data.Result);
          },
          error: function (xhr, textStatus, errorThrown) {
              var data = $.parseJSON(xhr.responseText);
              if (data === null)
                  alert(textStatus + " HttpCode:" + xhr.status);
              else
                  alert("ERROR: " + data.ResponseStatus.Message +
                      (data.ResponseStatus.StackTrace ? " \r\n Stack:" + data.ResponseStatus.StackTrace : ""));
          }
      });
  }
  </code></pre>
  
  <p>Again, this works in the RESTConsole if I first make the call to /auth/credentials properly and then follow that up with a call to /hello.</p>
  
  <p><strong>FINAL EDIT</strong>
  Following Stefan's advise, below, including many other links, I was finally able to get this working.  In addition to Stefan's code, I had to make one additional modification:</p>
  
  <pre><code>Plugins.Add(new CorsFeature(allowedHeaders: "Content-Type, Authorization"));
  </code></pre>
  
  <p>On to the next challenge:  Updating Jonas Eriksson's CustomAuthenticateAttibute code (which appears to be using an older version of ServiceStack as a couple of functions are no longer available.</p>
  
  <p>THANKS AGAIN STEFAN!!</p>