WebApi HttpPost not working on Windows Azure - c#

I am working on a sample project using WebApi2 with MVC with Angular and D3 api. I am facing an issue with my WebApi. Everything working fine on local machine with Azure database connection string but when i publish the same on Azure my HttpPost stops working while HttpGet is working fine.
[HttpPost]
[Route("api/dashboard/addnewassignment")]
public WebApiD3Sample.ViewModels.CoursePersonAssignmentModel AddNewCoursePersonAssignment([FromBody]WebApiD3Sample.ViewModels.CoursePersonAssignmentModel model)
{
if (ModelState.IsValid) {
var modelAfterSave = AssignmentService.AddAssignment(model);
return modelAfterSave;
}
ModelState.AddModelError("Invalid", "Not a Valid Save");
return model;
}
Error that i am facing on published
Failed to load resource: the server responded with a status of 500 (Internal Server Error)
http://sampledataweb.azurewebsites.net/api/dashboard/addnewassignment
Object
message: "An error has occurred."
__proto__: Object

I could send a post to your URL:
Status Code: 200 OK
Access-Control-Allow-Headers: Origin,X-Requested-With,Content-Type,Accept
Access-Control-Allow-Origin: *
Cache-Control: no-cache
Content-Encoding: gzip
Content-Length: 123
Content-Type: application/json; charset=utf-8
Date: Thu, 06 Mar 2014 18:48:25 GMT
Expires: -1
Pragma: no-cache
Server: Microsoft-IIS/8.0
Set-Cookie: ARRAffinity=dbb5756ce35e0494cf70c90b9aba80f70f92f607fb3ebb3e7dffe4ecc1aba24a;Path=/;Domain=sampledataweb.azurewebsites.net WAWebSiteSID=696c72c37b2e472b90f6033923558edd; Path=/; HttpOnly
Vary: Accept-Encoding
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
so the problem is in your CoursePersonAssignmentModel or AssignmentService.AddAssignment method. Install a nuget to log (i.e Elmah) and it will help you to catch the error. Another great option, you can debug using intellitrace: http://blogs.msdn.com/b/zainnab/archive/2013/02/12/understanding-intellitrace-part-i-what-the-is-intellitrace.aspx

It doesn't appear to be a cross domain issue, but just to make sure, did you allow it in your web.config?
<system.webServer>
<httpProtocol>
<customHeaders>
<remove name="Access-Control-Allow-Origin" />
<remove name="Access-Control-Allow-Headers" />
<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>

Related

Windows authentication with SOAP service and IIS failing

I have a client that sends a simple web request to a SOAP service. It is a simple C# program that uses the WSDL file of the service to create a client. The service is hosted on IIS 8.5 and Windows Server 2012. It works fine when using anonymous authentication but it fails with Windows authentication. Both client and service are in the same domain, user permissions are also fine.
I configured IIS so that it disables all forms of authentication except Windows authentication (Negotiate, NTLM). The client is configured so that it uses Windows as the client credential type.
When I send a request I get the following error:
"The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate, NTLM'"
I then tried out a tool I found on github called "WebServiceStudio". With that tool I set the WSDL, selected my request method and it worked, even with Windows authentication.
I looked at both attempts with Wireshark and noticed that the WebServiceStudio request immediately sends the Negotiate token with the first request while my own client sends the token in the second request, which to my understanding is how Windows authentication usually works.
I tried on IIS side but nothing worked so far:
Changed authentication order (Negotiate, NTLM and NTLM, Negotiate)
Changed authentication to only Negotiate
Changed extended protection in the advanced settings (neither option made a difference)
Verified that the WindowsAuthentication and WindowsAuthenticationModule were both installed
My goal is that my own C# client can successfully authenticate with Windows authentication.
Here's the C# client's configuration:
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
<system.serviceModel>
<client>
<endpoint address="server address" binding="basicHttpBinding"
bindingConfiguration="MyContractSoap" contract="MyContract.MyContractSoap" />
</client>
<bindings>
<basicHttpBinding>
<binding name="MyContractSoap">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" proxyCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
And here is the wireshark data of my client's request:
POST /ABC/ShipmentDocuments.asmx HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: "ABC/DocumentShipped"
Host: sdespte3
Content-Length: 333
Expect: 100-continue
Accept-Encoding: gzip, deflate
<!-- Server rejects request and states authentication method -->
HTTP/1.1 401 Unauthorized
Cache-Control: private
Content-Type: text/html
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Tue, 18 Feb 2020 10:20:01 GMT
Content-Length: 1344
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<title>401 - Nicht autorisiert: Zugriff aufgrund ung.ltiger Anmeldeinformationen verweigert.</title>
</head>
<body>
<div id="header"><h1>Serverfehler</h1></div>
<div id="content">
<div class="content-container"><fieldset>
<h2>401 - Nicht autorisiert: Zugriff aufgrund ung.ltiger Anmeldeinformationen verweigert.</h2>
<h3>Die angegebenen Anmeldeinformationen berechtigen Sie nicht, dieses Verzeichnis oder diese Seite anzuzeigen.</h3>
</fieldset></div>
</div>
</body>
</html>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body>Request data here</s:Body></s:Envelope>
<!-- We send the negotiate token -->
POST /ABC/ShipmentDocuments.asmx HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: "ABC/DocumentShipped"
Accept-Encoding: gzip, deflate
Authorization: Negotiate YIIHog...Token here
Host: abc
Content-Length: 333
Expect: 100-continue
<!-- Rejected again, unsure why -->
HTTP/1.1 401 Unauthorized
Cache-Control: private
Content-Type: text/html
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Tue, 18 Feb 2020 10:20:01 GMT
Content-Length: 1344
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<title>401 - Nicht autorisiert: Zugriff aufgrund ung.ltiger Anmeldeinformationen verweigert.</title>
<style type="text/css">
And finally the wireshark data of the other tool that worked:
POST /ABC/ShipmentDocuments.asmx HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: "ABC/DocumentShipped"
Authorization: Negotiate YIILV...Token here
Host: sdespiis1
Content-Length: 415
Expect: 100-continue
HTTP/1.1 100 Continue
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body>Request body here</soap:Body></soap:Envelope>
<!-- Accepted -->
HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
Persistent-Auth: false
X-Powered-By: ASP.NET
WWW-Authenticate: Negotiate oYG2MIGzo... Token here
Date: Tue, 18 Feb 2020 15:24:39 GMT
Content-Length: 295
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body>Body here</soap:Body></soap:Envelope>
Update: Here is the client's source code to call the service.
Program:
class Program
{
static void Main(string[] args)
{
sendWebRequest();
}
static int _orderId = 1;
static int _mandant = 1;
static string _sId = "0123456789012345678901";
static string _isShipped = "eingeliefert";
static void sendWebRequest()
{
Console.WriteLine("Start webrequest Orderid: {0}, mandant: {1}, sId: {2}, isShipped: {3}", _orderId, _mandant, _sId, _isShipped);
WebserviceManager wm = new WebserviceManager();
wm.Open();
wm.SetStateToShipped(_orderId, _mandant, _sId, _isShipped);
wm.Close();
Console.WriteLine("Webrequest erfolgreich");
}
}
WebserviceManager:
public class WebserviceManager
{
protected MyContract.MyContractSoapClient _soapClient;
public WebserviceManager()
{
}
public void Open()
{
_soapClient = createWebServiceClient();
try
{
_soapClient.Open();
}
catch (Exception ex)
{
Logging.Error("Open", ex);
throw ex;
}
Logging.Info("_soap-Client open");
}
public void Close()
{
_soapClient.Close();
}
public void SetStateToShipped(int orderNo, int mandant, string sId, string isShipped)
{
_soapClient.DocumentShipped(orderNo, mandant, sId, isShipped);
}
protected MyContract.MyContractSoapClient createWebServiceClient()
{
return new MyContract.MyContractSoapSoapClient();
}
}
So it looks like the impersonation was not properly set up. I added the following line in my client program, right after creating the client object:
protected MyContract.MyContractSoapClient createWebServiceClient()
{
var client = new MyContract.MyContractSoapSoapClient();
client.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
return client;
}
And now Windows authentication works as expected!

Asp.Net MVC WebApi CORS Request fails - no proposed solutions affecting the outcome

I have an Asp.Net NVC5 web application (running under Visual Studio 2017) on localhost:59569 (SiteApi). I have a second website (also running under Visual Studio 2017) on localhost:61527 (SiteClient) where a page once loaded makes the following api call to SiteApi:
$http({
url: 'http://localhost:59569/api/V2/' + alias,
method: 'POST',
data: pm,
xhrFields: { withCredentials: true },
headers: { 'Content-Type': 'application/json; charset=utf-8' }
})
.then(th, ex);
NOTE: I have tried this with and without the xhrFields + withCredentials information using Microsoft IE, Microsoft Edge and Chrome.
Back on SiteApi the resulting preflight call for OPTIONS is intercepted by the following code in Global.asax which executes exactly as written and I can trace through the if statement when an inbound call for OPTIONS triggers it.
protected void Application_BeginRequest()
{
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
{
Response.Clear();
Response.Headers.Add("Access-Control-Allow-Origin", "*");
Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, Session");
Response.Flush();
Response.End();
}
}
The intention being to send the desired headers back to the client to allow CORS to function properly - however immediately after this code is executed the web page back on SiteClient reports that the request has been blocked due to missing 'Access-Control-Allow-Origin' header is missing and I can see that none of the headers I have specified have made it back to the client.
In an attempt to have CORS work I have the following nuget packages installed on the SiteAPI project.
Microsoft.AspNet.Cors
Microsoft.AspNet.WebApi.Cors
I adjusted the WebApiConfig.Register() method to include:
// Web API configuration and services
config.EnableCors();
I have tried many variations of adding the filter attributes to my controller like so:
[EnableCors("*", "*", "*", SupportsCredentials = true)]
I have tried adding my own custom ActionFilterAttribute from solutions found in other CORS related questions on stackoverflow - for example (among various others):
public override void OnActionExecuting(System.Web.Mvc.ActionExecutingContext filterContext)
{
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
base.OnActionExecuting(filterContext);
I have the following to my web.config file:
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
I have ALL these solutions live in my project and in spite of this I still get CORS errors on the client side.
So the caveat here is that I also have a custom filter that looks up security on each API call - which works fine with ALL calls made from pages running on SiteApi. In the case of calls from SiteClient (CORS calls) the security filter never fires at all though I am getting 401 errors reported on the client in addition to the errors due to the missing CORS related headers.
I have cleared the caches of all browsers and the server itself. This is my first time working with CORS and I'm already exhausted from working with what really should be a simple solution. Looking for solutions here and would appreciate some help from those in the know.
Request Headers:
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 2
Content-Type: application/json; charset=UTF-8
Host: localhost:59569
Origin: http://localhost:61527
Referer: http://localhost:61527/Home/Index
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36 Edg/80.0.361.54
Response Headers:
Cache-Control: private
Content-Length: 6115
Content-Type: text/html; charset=utf-8
Date: Wed, 19 Feb 2020 00:46:06 GMT
Server: Microsoft-IIS/10.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcbngyMDA4MjZcRGV2XFRlY2hJVFxFQVNJV2ViQXBwXGFwaVxWMlxHZXRDb21tYW5kcw==?=
This is the flow I use. Sometimes browsers don't like "*". Other times, browsers don't like localhost, either. This is the logic I use (modify the allow headers as you see fit). It could be the fact that you aren't allowing the access control headers in your allowed headers, too:
[Add this to Global.asax]
protected void Application_BeginRequest(object sender, EventArgs e)
{
var originKey =
Request.Headers.AllKeys.FirstOrDefault(
a => a.Equals("origin", StringComparison.InvariantCultureIgnoreCase));
if (originKey != null && Request.HttpMethod == "OPTIONS"))
{
// Optional Whitelist check here can return without the headers below to reject CORS
Response.Headers.Add("Access-Control-Allow-Origin", Request.Headers[originKey]);
Response.Headers.Add("Access-Control-Allow-Credentials", "true");
Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUSH, DELETE, OPTIONS");
Response.Headers.Add("Access-Control-Allow-Headers",
"Authorization, Content-Type, Access-Control-Allow-Headers, X-Requested-With, Access-Control-Allow-Method, Accept");
Response.Flush();
Response.End();
return;
}
}

WEB API error-404 - "Message": "The requested resource does not support http method 'PUT'."

HTTP/1.1 405 Method Not Allowed
Cache-Control: no-cache
Pragma: no-cache
Allow: GET,POST
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcUHJvamVjdHNcZG90TmV0XFdlYkFQSVxBZFNlcnZpY2VcQWRTZXJ2aWNlXGFwaVxpbXByZXNzaW9uXDE1?=
X-Powered-By: ASP.NET
Date: Tue, 06 May 2014 14:10:35 GMT
Content-Length: 72
{"message":"The requested resource does not support http method 'PUT'."}
I want to generate PUT and DELETE request using POSTMAN but I got following message from POSTMAN.
Even I have implemented all the suggestions given by ASP.NET site.
Below is Web API c# code:
// PUT: api/Students/5
[HttpPut]
[ResponseType(typeof(void))]
public IHttpActionResult PutStudent(decimal Enrollment_no, Student student)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (Enrollment_no != student.Enrollment_no)
{
return BadRequest();
}
db.Entry(student).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!StudentExists(Enrollment_no))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
Nothing has worked as I'm still getting a 405 response when trying to issue a "PUT" command against my Web API project.
Your back end api is only allowing GET and POST requests(see response header Allow ), hence to generate PUT/DELETE request API should add support for the same.
You can configure this by modifying web.config of your ASP.NET Web API. Try to find the following line:
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
Replace it with:
<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" />
Please refer here for more information.

HTTP 405 Errors after Publishing Web API 2 Applications

I have a Web Api Controller and i have tested all actions on localhost and it works well.But when i Published it on Web Server,Just Actions with [HttpGet] works and [HttpPost] Actions return Http 405 error
public class ContentController : ApiController
{
[HttpGet]
public async Task<IHttpActionResult> AdvantageList()
{
//return ok 200
}
[HttpPost]
public async Task<IHttpActionResult> SaveAdvantage(ContentModel model)
{
//return 405
}
}
I used below method on client
var r = await ClientManager.Client.PostAsJsonAsync("api/Content/SaveAdvantage", Advantage);
But it will retrun below response form server.I Used PostAsJsonAsync method but it says that The requested resource does not support http method 'GET'
Does any one know why?
{
StatusCode: 405, ReasonPhrase: 'Method Not Allowed', Version: 1.0, Content: System.Net.Http.StreamContent, Headers:
{
Pragma: no-cache
X-Powered-By-Plesk: PleskWin
Connection: close
Cache-Control: no-cache
Date: Fri, 29 Sep 2017 08:53:51 GMT
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Content-Length: 72
Allow: POST
Content-Type: application/json; charset=utf-8
Expires: -1
}}
And
"{\"message\":\"The requested resource does not support http method 'GET'.\"}"
I have the below in my web api config:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{action}");
config.Routes.MapHttpRoute("WithId", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });
config.Routes.MapHttpRoute("TwoId", "api/{controller}/{action}/{id}/{id2}", new { id = RouteParameter.Optional, id2 = RouteParameter.Optional });
config.MapHttpAttributeRoutes();
var formatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
formatter.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
}
}
I have below handlers in Web.config
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
I use this webapi2 application in my winform application.
It is the http error code who tell us that it is a right problem. Have a look at : https://fr.wikipedia.org/wiki/Liste_des_codes_HTTP
In hosting Setting in my web server ,had a property Preferred domain ,i changed it to none and after that it worked properly
You have a problem of right on the web server. 405 http code means that the post method is not allowed to use from your web server. Make you sure that you are authenticated when you send request and also make you sure that your request contain some token for authentication.

When authenticating WCF service on IIS AuthenticateRequest is called only first time

I have a working implementation of OData WCF service which now need to be published in IIS with basic custom authentication.
Implementation is based on Microsoft OData example and works perfectly fine under the IIS Express. When I publish it to IIS 7.5 with only Basic Authentication enabled, AuthenticateRequest handler is only called on initial request, which returns status code 401 and asks to authenticate.
AuthenticateRequest is no longer called on subsequent requests. When debugging the service on IIS, BeginRequest is definitely called, it's just AuthenticateRequest not being present in the pipeline? Both are called every request in IIS Express.
IIS Authentication configuration:
IHttpModule code:
public class BasicAuthModule: IHttpModule
{
// based on http://msdn.microsoft.com/en-gb/data/gg192997.aspx
public void Init(HttpApplication app)
{
app.AuthenticateRequest += AuthenticateRequest;
app.BeginRequest += BeginRequest;
}
private void BeginRequest(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
if(app.Context == null)
{
throw new Exception("Will not happen");
}
}
private void AuthenticateRequest(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
if(!app.Request.Headers.AllKeys.Contains("Authorization"))
{
CreateNotAuthorizedResponse(app, 401, 1, "Please provide Authorization headers with your request.");
app.CompleteRequest();
}
else if(!BasicAuthProvider.Authenticate(app.Context))
{
CreateNotAuthorizedResponse(app, 401, 1, "Logon failed.");
app.CompleteRequest();
}
}
private static void CreateNotAuthorizedResponse(HttpApplication app, int code, int subCode, string description)
{
var response = app.Context.Response;
// response.Status = "401 Unauthorized";
response.StatusCode = code;
response.SubStatusCode = subCode;
response.StatusDescription = description;
// response.AppendHeader("WWW-Authenticate", "Basic");
// response.End();
}
public void Dispose()
{
}
}
Web.config:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="BasicAuthModule" type="WcfTestService.BasicAuthModule"/>
</modules>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
And the question: why authentication works in Visual Studio 2012 debug server but not in IIS 7.5?
Complete test project can be downloaded from here.
Edit:
I commented out excessive testing code in the CreateNotAuthorizedResponse function and response.End() which caused an exception (I added it last minute before posting).
When inspecting requests it looks like everything should work except that Cookie may be causing IIS to skip authentication for some reason. Below first 2 raw request - reply pairs:
Request 1:
GET http://localhost:8080/test/ HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,pl;q=0.6
Cookie: ASPSESSIONIDAQRDDBTR=BPCFKGDDCGJLPFKHEPOLPMFK; __RequestVerificationToken_L2RlbGl2ZXJ50=j0o-RDC12Z_E1o1nnXU_9iFaThUEPXRXDNKepqoX2fmgjg8gRB6Hi9fs3MSGxUvYQs6tJ0Jxsf6U20WKWpOrj4azgL_VpVzQHcNyJghUrKg1; __RequestVerificationToken=uOeCVgZDguOs3mRA7O4nhj88wJ_mFR6t1QN7vl7mOPGaNBoEnVFmIQVoUwxim8NbODJKMz5fBuAoPKo7Ek-4JeujsOIyIxjRB1xS_JaFF381; .ASPXAUTH=C2965A60E4BB162123A2CDDA8FD825C9DF3625116E5722C9B873BA64F041CCDCAB098EA3A208C2061D8D5746BC0832413105BA274C1B37DB8276471D49DE12562E4E93933289828427F559057519E75421493909E215EAA0DFB4C8DBE213EAC19AB6025EA715658A8D57CAFA308F7AC4A9051687777D2E82B7A2552917466E7C0BFA0C23EEE272F7E83C3718371375358B1199F155FB882EF8F5082CB28F6E030146DE365B5E4D8FE25E55EDD3F03788
Reply 1: (created by CreateNotAuthorizedResponse method)
HTTP/1.1 401 Please provide Authorization headers with your request.
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
WWW-Authenticate: Basic realm="localhost"
X-Powered-By: ASP.NET
Date: Mon, 20 Oct 2014 13:03:14 GMT
Content-Length: 6607
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>IIS 7.5 Detailed Error - 401.1 - Please provide Authorization headers with your request.</title>
Request 2 (when entered test:test - dGVzdDp0ZXN0):
GET http://localhost:8080/test/ HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Authorization: Basic dGVzdDp0ZXN0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,pl;q=0.6
Cookie: ASPSESSIONIDAQRDDBTR=BPCFKGDDCGJLPFKHEPOLPMFK; __RequestVerificationToken_L2RlbGl2ZXJ50=j0o-RDC12Z_E1o1nnXU_9iFaThUEPXRXDNKepqoX2fmgjg8gRB6Hi9fs3MSGxUvYQs6tJ0Jxsf6U20WKWpOrj4azgL_VpVzQHcNyJghUrKg1; __RequestVerificationToken=uOeCVgZDguOs3mRA7O4nhj88wJ_mFR6t1QN7vl7mOPGaNBoEnVFmIQVoUwxim8NbODJKMz5fBuAoPKo7Ek-4JeujsOIyIxjRB1xS_JaFF381; .ASPXAUTH=C2965A60E4BB162123A2CDDA8FD825C9DF3625116E5722C9B873BA64F041CCDCAB098EA3A208C2061D8D5746BC0832413105BA274C1B37DB8276471D49DE12562E4E93933289828427F559057519E75421493909E215EAA0DFB4C8DBE213EAC19AB6025EA715658A8D57CAFA308F7AC4A9051687777D2E82B7A2552917466E7C0BFA0C23EEE272F7E83C3718371375358B1199F155FB882EF8F5082CB28F6E030146DE365B5E4D8FE25E55EDD3F03788
Response 2 (BeginRequest called but not AuthenticateRequest):
HTTP/1.1 401 Unauthorized
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
WWW-Authenticate: Basic realm="localhost"
X-Powered-By: ASP.NET
Date: Mon, 20 Oct 2014 13:03:17 GMT
Content-Length: 6531
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>IIS 7.5 Detailed Error - 401.1 - Unauthorized</title>
I think you are mixing up IIS built-in basic authentication with your own custom authentication module. The short answer is to disable Basic Authentication in IIS and enable Anonymous. This will pass all the auth work onto asp.net.
If your are testing in VS I'm assuming you are doing so via a browser that is auto launched when you hit F5.
With basic auth turned on IIS initially responds with a 401 which causes the browser to display the login form.
The credentials you enter there have to be valid windows credentials, which IIS validates against your windows accounts. Once IIS has validated these credentials it will pass the request along to your code.
If you enter valid windows credentials the event is raised but your code will reject it because the credentials are not test/test and return a 401.1
If you enter test/test then IIS is rejecting the credentials and sends back a 401 so your event is never called.
Final word: You should be testing your web service using an http client (e.g. unit test with System.Net.WebClient), or use a chrome plugin (postman/devhttp) to test at the http level. If you are already doing this then forgive my assumption.

Categories

Resources