I have a WCF service, IIS hosted. It is protected with Basic Authentication.
When I browse with a browser, I get a 401 (nt challenge) and a 200 (successful response).
The same website, page etc, with a WCF request via a console app, I get 401, then 404 (page not found).
Both use the same username and password which are correct. The machine is just a desktop for development. Not on a domain. The host is hostwebsite.local via host file binding to 127.0.0.1
Here are the IIS logs.
The first two lines are the failed WCF called. The last 2 lines is the successful browser call.
The only real difference is the GET/POST. The WCF works when authentication is anonymous.
How can I debug this issue? thank you.
#Software: Microsoft Internet Information Services 7.5
#Version: 1.0
#Date: 2011-03-31 22:53:58
#Fields: date time s-sitename s-computername s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs-version cs(User-Agent) cs(Cookie) cs(Referer) cs-host sc-status sc-substatus sc-win32-status sc-bytes cs-bytes time-taken
2011-03-31 22:56:37 W3SVC2 MIKEV-WS 127.0.0.1 POST /Services/EchoService.svc - 80 - 127.0.0.1 HTTP/1.1 - - - hostwebsite.local 401 2 5 6633 362 3
2011-03-31 22:56:37 W3SVC2 MIKEV-WS 127.0.0.1 POST /Services/EchoService.svc - 80 admin 127.0.0.1 HTTP/1.1 - - - hostwebsite.local 404 0 0 210 568 2
2011-03-31 22:57:07 W3SVC2 MIKEV-WS 127.0.0.1 GET /Services/EchoService.svc - 80 - 127.0.0.1 HTTP/1.1 Mozilla/5.0+(Windows;+U;+Windows+NT+6.1;+en-US)+AppleWebKit/534.16+(KHTML,+like+Gecko)+Chrome/10.0.648.133+Safari/534.16 - - hostwebsite.local 401 2 5 6633 442 1
2011-03-31 22:57:10 W3SVC2 MIKEV-WS 127.0.0.1 GET /Services/EchoService.svc - 80 admin 127.0.0.1 HTTP/1.1 Mozilla/5.0+(Windows;+U;+Windows+NT+6.1;+en-US)+AppleWebKit/534.16+(KHTML,+like+Gecko)+Chrome/10.0.648.133+Safari/534.16 - - hostwebsite.local 200 0 0 1287 485 23
New Information
Problem is now solved and I have listed the answer below.
There was a configuration error causing the listening server to listen on http://hostwebsite.local/Services/EchoService.svc/Services/EchoService.svc
instead of
http://hostwebsite.local/Services/EchoService.svc
I cleared the address in the server endpoint which was /Services/EchoService.svc
<services>
<service name="API.Proxy.EchoProxy" behaviorConfiguration="MyServiceTypeBehaviors">
<endpoint address="[CLEARED]" binding="basicHttpBinding" contract="API.Contract.IEcho" bindingConfiguration="NewBinding" />
The client config already had the address
<client>
<endpoint address="http://hostwebsite.local/Services/EchoService.svc" binding="basicHttpBinding" bindingConfiguration="SecureBinding" contract="API.Contract.IEcho" name="SecureEndpoint">
Notice your one request... is POST and the other is a GET... perhaps that is the issue!
Related
I'm trying to config a web api with SignalR enabled, so I can push real-time information to the clients via websockets. In front of the api I have a nginx reverse ssl proxy running in a docker container.
Clients can connect just fine via the reverse proxy when ssl is disabled in the nginx configuration:
server {
listen 55555;
# listen 55555 ssl;
ssl_certificate /config/keys/cert.crt;
ssl_certificate_key /config/keys/cert.key;
location / {
proxy_pass http://192.168.1.175:50000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
But when I configure the proxy to listen for ssl the clients can't seem to connect, or at least the client gets a "The server disconnected before the handshake could be started" IOException after what appears to be a time out.
WebAPI log:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 POST http://192.168.1.150/chatHub/negotiate?negotiateVersion=1 - 0
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint '/chatHub/negotiate'
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionManager[1]
New connection i-HjjQP9EsA_rBTX7vFs2Q created.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionDispatcher[10]
Sending negotiation response.
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint '/chatHub/negotiate'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished HTTP/1.1 POST http://192.168.1.150/chatHub/negotiate?negotiateVersion=1 - 0 - 200 316 application/json 117.3988ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 POST http://192.168.1.150/chatHub/negotiate?negotiateVersion=1 - 0
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint '/chatHub/negotiate'
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionManager[1]
New connection K0y7OI3-3KvPIXWV92HEkA created.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionDispatcher[10]
Sending negotiation response.
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint '/chatHub/negotiate'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished HTTP/1.1 POST http://192.168.1.150/chatHub/negotiate?negotiateVersion=1 - 0 - 200 316 application/json 11.6330ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 GET http://192.168.1.150/chatHub?id=zdDUpBZ-RsnQgEZsJ9Sctg - -
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint '/chatHub'
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionDispatcher[4]
Establishing new connection.
dbug: Microsoft.AspNetCore.SignalR.HubConnectionHandler[5]
OnConnectedAsync started.
dbug: Microsoft.AspNetCore.SignalR.HubConnectionContext[2]
Handshake was canceled.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionManager[2]
Removing connection zdDUpBZ-RsnQgEZsJ9Sctg from the list of connections.
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint '/chatHub'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished HTTP/1.1 GET http://192.168.1.150/chatHub?id=zdDUpBZ-RsnQgEZsJ9Sctg - - - 200 - text/event-stream 60079.4344ms
I've tried including the following in the WebApplication settings:
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.KnownProxies.Add(IPAddress.Parse("192.168.1.150")); // Proxy Server IP
});
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost
});
But as far as I can tell, it doesn't really make a difference.
I'm unsure whether this is a nginx reverse proxy/sll or a Webpi/SignalR issue. Any ideas? :)
EDIT
It seems that my first error I describe is very easy to reproduce. Actually, Google Run fails to run any GRPC query on a .NET5 GRPC server it seems (at least, it did work before but as of today, February 21st, it seems that something changed). To reproduce:
Create a .NET5 GRPC server (also fails with .NET6):
dotnet new grpc -o TestGrpc
Change Program.cs so that it listens on $PORT, typically:
public static IHostBuilder CreateHostBuilder(string[] args)
{
var port = Environment.GetEnvironmentVariable("PORT") ?? "8080";
var url = string.Concat("http://0.0.0.0:", port);
return Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>().UseUrls(url);
});
}
A very simple Dockerfile to have an image for the server (fails also with a more standard one, like here):
FROM mcr.microsoft.com/dotnet/sdk:5.0
COPY . ./
RUN dotnet restore ./TestGrpc.csproj
RUN dotnet build ./TestGrpc.csproj -c Release
CMD dotnet run --project ./TestGrpc.csproj
Build and push to Google Artifcats Registry.
Create a Cloud Run instance with HTTP/2 enabled (Ketrel requires HTTP/2 so we need to set
HTTP/2 end-to-end, yet I tested without as well but it's not better).
Use Grpcurl for instance and try:
grpcurl {CLOUD_RUN_URL}:443 list
And you will obtain the same error as I got with my (more complex) project:
Failed to list services: rpc error: code = Unavailable desc = upstream connect error or disconnect/reset before headers. reset reason: remote reset
On the Google Cloud Run instance I only have the log:
2022-02-21T16:44:32.528530Z POST 200 1.02 KB 41 ms grpcurl/v1.8.6 grpc-go/1.44.1-dev https://***/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo
(I don't really understand why it's a 200 though... and never seems to reach the actual server implementation, just as if there was some kind of middleware blocking the query to reach the implementation... )
I'm pretty sure this used to worked as I started my project this way (and then changed the protos, the service, etc. ). If anyone has a clue I'd be more than grateful :-)
INITIAL POST (less precise than explanations above but I leave it here if it may give clues)
I have a server running within a Docker (.NET5 GRPC application). This server, when deployed locally works perfectly fine. But recently I have an error when I deploy it on Google Cloud Run: upstream connect error or disconnect/reset before headers. reset reason: remote reset when it was working fine before. I keep on having this error from any client I use, for instance with Curl:
curl -v https://{ENDPOINT}/{Proto-base}/{Method} --http2
* Trying ***...
* TCP_NODELAY set
* Connected to *** (***) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=*.a.run.app
* start date: Feb 7 02:07:06 2022 GMT
* expire date: May 2 02:07:05 2022 GMT
* subjectAltName: host "***" matched cert's "*.a.run.app"
* issuer: C=US; O=Google Trust Services LLC; CN=GTS CA 1C3
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x5564aad30860)
> GET /{Proto}/{Method} HTTP/2
> Host: ***
> user-agent: curl/7.68.0
> accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 503
< content-length: 85
< content-type: text/plain
< date: Mon, 21 Feb 2022 13:51:31 GMT
< server: Google Frontend
< traceparent: 00-5a74487dafb5687961deeb17e0158ca9-5ab63cd23680e7d7-01
< x-cloud-trace-context: 5a74487dafb5687961deeb17e0158ca9/6536478782730069975;o=1
< alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
<
* Connection #0 to host *** left intact
upstream connect error or disconnect/reset before headers. reset reason: remote reset
Same happens with Grpcurl:
grpcurl ***:443 list {Proto-base}
Failed to list methods for service "***.Company": rpc error: code = Unavailable desc = upstream connect error or disconnect/reset before headers. reset reason: remote reset
I cannot find much resource on this error as most of the threads I read deal with another type of reset reason (like protocol, or connection, etc.). But I strictly have no idea what remote reset means and what I did wrong.
Looking at the logs in Google Cloud Run, I can see that the server is definitly hit, though I added trace logging in the route which is not triggered, hence it never reaches my code:
2022-02-21T14:44:22.840580Z POST 200 1.01 KB 1 msgrpc-python/1.44.0 grpc-c/22.0.0 (linux; chttp2) https://***/{Protos-base}/{Method}
(if I reached my code it should print some "Hellos" everywhere which it doesn't)
Has anyone ever found this?
P.S.: there are many things around about Envoy, but I don't even use this. I simply have a Cloud Run instance (with HTTP/2 - and I tried without but it fails due to protocol issue).
It is an actual bug from Envoy and Google Cloud Run. There is a quick fix if you're using .NET6, otherwise it's a bit more hacky. I will just copy here the answer provided by Amanda Tarafa Mas from Google Cloud Platform on the github issue I opened:
Here are the potential fixes:
When using .NET 6 you can set KestrelServerOptions.AllowAlternateSchemes to true.
If on a lower .NET version, consider something like GRPC :scheme pseudo-header passed from proxy/loadbalancer causes ConnectionAbortedException dotnet/aspnetcore#30532 (comment). Or consider upgrading to .NET 6.
What's happening:
Cloud Run has dependency on Envoy, which has a behavior change since 04/15/2021, see "preserve_downstream_scheme" in release notes:
https://www.envoyproxy.io/docs/envoy/latest/version_history/v1.18.0
Envoy recently removed the old behaviour: https://www.envoyproxy.io/docs/envoy/latest/version_history/current#removed-config-or-runtime
In turn, this exposes this .NET issue: GRPC :scheme pseudo-header passed from proxy/loadbalancer causes ConnectionAbortedException dotnet/aspnetcore#30532, for which the Kestrel configuration flag was added, but only for .NET 6.
I'm looking into having this documented somewhere. #meteatamel can you update the tutorial so that it uses the Kestrel option?
For me setting KestrelServerOptions.AllowAlternate was enough to make my GRPC server work again.
As #Craig said, you can track the issue here and see if it gets resolved.
I am using Nginx + Websockets on a precise 64 vagrant box, with c#/mono for the app server. The goal is to serve up static content directly through Nginx, and handle both plain 'ol http service requests (on /service) and also websocket requests (on /webSocket) all on the same port. Here's the relevant conf:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80 default_server;
# (1)
location / {
root /var/www;
index index.html;
}
# (2)
location /service {
add_header Access-Control-Allow-Origin *;
proxy_pass http://localhost:9000;
}
# (3)
location /webSocket {
proxy_pass http://localhost:9000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
Most of it is working well. Static content, yes, service requests, yes, and even the first part of websockets. I am getting a well-formed 101 Switching Protocols request from my client (Firefox or Chrome). I am making a nice http upgrade response and sending it. And then the client does... nothing... nothing is received.
But the crazy thing is, when I give up and manually kill my server side app, and the client web socket closes with error, THEN the Response Headers show up on the client browser debugger. The whole thing looks like:
REQUEST HEADERS
Request URL: http://localhost:8086/webSocket
Request Method: GET
Status Code: HTTP/1.1 101 Switching Protocols
Request Headers 16:18:50.000
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: Nx0sUAemOFWM2rsaCAJpfQ==
Sec-WebSocket-Extensions: permessage-deflate
Pragma: no-cache
Origin: http://localhost:8086
Host: localhost:8086
Connection: keep-alive, Upgrade
Cache-Control: no-cache
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
RESPONSE HEADERS Δ19660ms
Upgrade: websocket
Transfer-Encoding: chunked
Server: nginx/1.1.19
Sec-WebSocket-Accept: gNiAeqxcVjkiReIpdtP0EZiClpg=
Date: Mon, 08 Jun 2015 20:18:48 GMT
Connection: keep-alive
NO RESPONSE BODY Δ0ms
There's no evidence that my server app is not flushing out its send data right away - I'm using async TcpSocket.BeginSend and FinishSend and the send seems to complete right away. And it works fine on plain http service comm.
So where is my websocket message data going??? It seems like Nginx doesn't want to send it back to my client, except until I close the Tcp connection from the server side.
Has anybody experienced something like this before. Everything I've read on Nginx and Websockets is concerned with the basic setup that gets the hop-by-hop upgrade working, and I've got that. No one has anything to say as to why sending back from the server side doesn't seem to go anywhere.
I have a RTP multicast stream from ffmpeg that requires users to use external SDP files, as this sometimes becomes a problem I was thinking of wrapping the stream using RTSP.
I have an application that already makes some management for the RTP stream, so it would be useful to have the RTSP wrapper inside it as well, although I don't want the wrapper to do anything beyond delivering the SDP information. Right now I'd say I'm correctly delivering the SDP information (otherwise it's stuck in that request), however I'm not getting any PLAY command, the player is stuck after the SETUP request, so I guess my reply is wrong, but after testing many different values for the Transport header I haven't been able to get anything beyond this point.
This is the SDP:
v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
c=IN IP4 236.0.0.1
t=0 0
a=tool:libavformat 56.7.102
m=video 2000 RTP/AVP 96
b=AS:500
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1
This is a sample SETUP request from VLC:
SETUP rtsp://127.0.0.1:34343/live.sdp/ RTSP/1.0
CSeq: 4
User-Agent: LibVLC/2.1.5 (LIVE555 Streaming Media v2014.05.27)
Transport: RTP/AVP;multicast;client_port=2000-2001
And one of many replies I've tried:
RTSP/1.0 200 OK
CSeq: 4
Transport: RTP/AVP;multicast;client_port=2000-2001;source=236.0.0.1;port=2000-2001
Session: 0456804596
I've tried using destination instead of source, server_port instead of port, also, although the RTP multicast port is 2000, I've seen the streaming is also using other ports like 57927 and 57928, so I've tried those ones as well, etc.
Just my two cents, but from the logical point of view a PLAY command for a multicast RTSP stream does not make any sense since the clients will get the media as soon as they join the group. The multicast stream as such does not have state.
Is the multicast RTP stream active at this point? Maybe VLC is actually joining the group after the SETUP response but no data is being transmitted to it? Also you can use VLC error log to see what is going on.
EDIT
Here is an example RTSP session with a multicast stream between VLC and an IP camera:
DESCRIBE rtsp://192.168.3.142/stream/profile1=m RTSP/1.0
CSeq: 5
User-Agent: LibVLC/2.0.1 (LIVE555 Streaming Media v2011.12.23)
Accept: application/sdp
RTSP/1.0 200 OK
CSeq: 5
Connection: Keep-alive
Date: Sat, 10 Jan 2015 16:54:28 GMT
Content-Type: application/sdp
Content-Length: 352
v=0
o=- 0 0 IN IP4 192.168.3.142
s=rtsp://192.168.3.142/stream/profile1
t=0 0
a=control:*
m=video 2014 RTP/AVP 99
a=rtpmap:99 H264/90000
a=fmtp:99 sprop-parameter-sets=Z0LgKdoB4Aiflm4CAgwE,aM48gA==;packetization-mode=1;profile-level-id=42e029
a=control:rtsp://192.168.3.142/stream/profile1/AVCESEnc
a=framerate:30.0
c=IN IP4 239.100.10.10/1
SETUP rtsp://192.168.3.142/stream/profile1/AVCESEnc RTSP/1.0
CSeq: 6
User-Agent: LibVLC/2.0.1 (LIVE555 Streaming Media v2011.12.23)
Transport: RTP/AVP;multicast;client_port=2014-2015
RTSP/1.0 200 OK
CSeq: 6
Connection: Keep-alive
Date: Sat, 10 Jan 2015 16:54:28 GMT
Session: 241934337;timeout=60
Transport: RTP/AVP;multicast;destination=239.100.10.10;port=2014-2015;ttl=1
PLAY rtsp://192.168.3.142/stream/profile1=m RTSP/1.0
CSeq: 7
User-Agent: LibVLC/2.0.1 (LIVE555 Streaming Media v2011.12.23)
Session: 241934337
Range: npt=0.000-
RTSP/1.0 200 OK
CSeq: 7
Connection: Keep-alive
Date: Sat, 10 Jan 2015 16:54:28 GMT
Session: 241934337
RTP-Info: url=rtsp://192.168.3.142/stream/profile1/AVCESEnc;seq=14604;rtptime=3766807430
GET_PARAMETER rtsp://192.168.3.142/stream/profile1=m RTSP/1.0
CSeq: 8
User-Agent: LibVLC/2.0.1 (LIVE555 Streaming Media v2011.12.23)
Session: 241934337
RTSP/1.0 200 OK
CSeq: 8
Connection: Keep-alive
Date: Sat, 10 Jan 2015 16:54:29 GMT
Session: 241934337
TEARDOWN rtsp://192.168.3.142/stream/profile1=m RTSP/1.0
CSeq: 9
User-Agent: LibVLC/2.0.1 (LIVE555 Streaming Media v2011.12.23)
Session: 241934337
RTSP/1.0 200 OK
CSeq: 9
Connection: Close
Date: Sat, 10 Jan 2015 16:54:31 GMT
Session: 241934337
EDIT 2
As can be seen lower in the comments, Neverbirth pointed out that the issue was not in the SETUP command but in the HTTP headers for the DESCRIBE command - a wrong content length was used in the response. After fixing that the problem was solved.
I have written a Web Service using JAX-RS in Netbeans. This was deployed to a local Tomcat 7.0 server on my machine which used basic authentication for users to login and retrieve some XML.
I currently have the configuration set to use Windows Authentication using WAFFLE. I am trying to get a better understanding of what is happening.
I have tried following the tutorials on waffle to get this working:
Waffle Tutorials and Docs
I can consume the web service from:
Internet Explorer 10 (have intranet zones configured with User Authentication -> Automatic Logon only in intranet zone selected)
Google Chrome
This does not require me to enter credentials.
My colleague can consume the web service from:
FireFox (requires username and password entered in dialog)
However he cannot connect using Internet Explorer 9 with the same intranet zone settings and user authentication settings as me). My internet browsers are not prompting for username and password.
I thought everything would be OK so I wrote a .NET Client to consume and test the web service. This worked from my machine but did not work from a colleagues (even when I ran as my user).
Web Service Code and Configuration
Context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/MyWebApp">
<Valve className="waffle.apache.NegotiateAuthenticator" />
<Realm className="waffle.apache.WindowsRealm" />
</Context>
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<servlet>
<servlet-name>ServletAdaptor</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServletAdaptor</servlet-name>
<url-pattern>/My/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<security-role>
<role-name>Everyone</role-name>
</security-role>
<security-role>
<role-name>MyDomain\Users</role-name>
</security-role>
<security-constraint>
<web-resource-collection>
<web-resource-name>
Demo Application
</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>Everyone</role-name>
</auth-constraint>
</security-constraint>
<filter>
<filter-name>SecurityFilter</filter-name>
<filter-class>waffle.servlet.NegotiateSecurityFilter</filter-class>
<init-param>
<param-name>principalFormat</param-name>
<param-value>fqn</param-value>
</init-param>
<init-param>
<param-name>roleFormat</param-name>
<param-value>both</param-value>
</init-param>
<init-param>
<param-name>allowGuestLogin</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>impersonate</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>securityFilterProviders</param-name>
<param-value>
waffle.servlet.spi.NegotiateSecurityFilterProvider
waffle.servlet.spi.BasicSecurityFilterProvider
</param-value>
</init-param>
<init-param>
<param-name>waffle.servlet.spi.NegotiateSecurityFilterProvider/protocols</param-name>
<param-value>
NTLM
Negotiate
</param-value>
</init-param>
<init-param>
<param-name>waffle.servlet.spi.BasicSecurityFilterProvider/realm</param-name>
<param-value>WaffleFilterDemo</param-value>
</init-param>
</filter>
</web-app>
I copied all of the waffle files to C:\Program Files (x86)\Apache Software Foundation\Tomcat 7.0\lib (apart from waffle-tomcat5.jar and waffle-tomcat6.jar).
Web Service Client Consumer Code (C#)
HttpWebRequest request = null;
HttpWebResponse response = null;
String Xml;
// Create the web request
request = WebRequest.Create(this.UrlTextBox.Text) as HttpWebRequest;
request.AuthenticationLevel = AuthenticationLevel.MutualAuthRequired;
// the following lines did not make any difference. I've tried impersonation and the other enums
request.Credentials = CredentialCache.DefaultCredentials;
request.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation;
request.Method = "GET";
// Get response
using (response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
StreamReader reader = new StreamReader(response.GetResponseStream());
Xml = reader.ReadToEnd();
this.webBrowser1.DocumentText = Xml;
}
Tomcat Log from running web service from other machine
This log is when the .net client fails to authenticate.
12:06:59.715 [http-apr-9090-exec-57] DEBUG waffle.apache.NegotiateAuthenticator - GET /MyWebApp/My/xyz/instructions/get, contentlength: -1
12:06:59.715 [http-apr-9090-exec-57] DEBUG waffle.apache.NegotiateAuthenticator - authorization: <none>, ntlm post: false
12:06:59.715 [http-apr-9090-exec-57] DEBUG waffle.apache.NegotiateAuthenticator - authorization required
12:06:59.725 [http-apr-9090-exec-59] DEBUG waffle.apache.NegotiateAuthenticator - GET /MyWebApp/My/xyz/instructions/get, contentlength: -1
12:06:59.775 [http-apr-9090-exec-59] DEBUG waffle.apache.NegotiateAuthenticator - authorization: Negotiate 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, ntlm post: false
12:06:59.825 [http-apr-9090-exec-59] DEBUG waffle.apache.NegotiateAuthenticator - security package: Negotiate, connection id: 192.168.2.126:51836
12:06:59.825 [http-apr-9090-exec-59] DEBUG waffle.apache.NegotiateAuthenticator - token buffer: 1785 byte(s)
12:06:59.825 [http-apr-9090-exec-59] DEBUG waffle.apache.NegotiateAuthenticator - continue required: true
12:06:59.825 [http-apr-9090-exec-59] DEBUG waffle.apache.NegotiateAuthenticator - continue token: oX8wfaADCgEBoQsGCSqGSIL3EgECAqJpBGdgZQYJKoZIhvcSAQICAwB+VjBUoAMCAQWhAwIBHqQRGA8yMDEzMDUzMTExMDY1OVqlBQIDBpwGpgMCASmpERsPUVVPUlVNREVWLkxPQ0FMqhYwFKADAgEBoQ0wCxsJcGFuZGVyc29u
12:06:59.875 [http-apr-9090-exec-60] DEBUG waffle.apache.NegotiateAuthenticator - GET /MyWebApp/My/xyz/instructions/get, contentlength: -1
12:06:59.875 [http-apr-9090-exec-60] DEBUG waffle.apache.NegotiateAuthenticator - authorization: Negotiate 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, ntlm post: false
12:06:59.925 [http-apr-9090-exec-60] DEBUG waffle.apache.NegotiateAuthenticator - security package: Negotiate, connection id: 192.168.2.126:51836
12:06:59.925 [http-apr-9090-exec-60] DEBUG waffle.apache.NegotiateAuthenticator - token buffer: 1728 byte(s)
12:06:59.925 [http-apr-9090-exec-60] DEBUG waffle.apache.NegotiateAuthenticator - continue required: true
12:06:59.925 [http-apr-9090-exec-60] DEBUG waffle.apache.NegotiateAuthenticator - continue token: oXIwcKADCgEBomkEZ2BlBgkqhkiG9xIBAgIDAH5WMFSgAwIBBaEDAgEepBEYDzIwMTMwNTMxMTEwNjU5WqUFAgMIIqimAwIBKakRGw9RVU9SVU1ERVYuTE9DQUyqFjAUoAMCAQGhDTALGwlwYW5kZXJzb24=
When I run on my machine I get the following logging (including Request Headers from Fiddler):
GET http://padesktop:9090/MyWebApp/My/xyz/instructions/get?unit=XXX11&data-type=BOAI&datefrom=2012-01-10&dateto=2012-02-01 HTTP/1.1
Host: padesktop:9090
Connection: Keep-Alive
17:56:09.478 [http-apr-9090-exec-26] DEBUG waffle.apache.NegotiateAuthenticator - GET /MyWebApp/My/xyz/instructions/get, contentlength: -1
17:56:09.478 [http-apr-9090-exec-26] DEBUG waffle.apache.NegotiateAuthenticator - authorization: <none>, ntlm post: false
17:56:09.478 [http-apr-9090-exec-26] DEBUG waffle.apache.NegotiateAuthenticator - authorization required
GET http://padesktop:9090/MyWebApp/My/xyz/instructions/get?unit=XXX11&data-type=BOAI&datefrom=2012-01-10&dateto=2012-02-01 HTTP/1.1
Authorization: Negotiate YHwGBisGAQUFAqByMHCgMDAuBgorBgEEAYI3AgIKBgkqhkiC9xIBAgIGCSqGSIb3EgECAgYKKwYBBAGCNwICHqI8BDpOVExNU1NQAAEAAACXsgjiCQAJADEAAAAJAAkAKAAAAAYBsR0AAAAPUEFERVNLVE9QUVVPUlVNREVW
Host: padesktop:9090
17:56:11.489 [http-apr-9090-exec-28] DEBUG waffle.apache.NegotiateAuthenticator - GET /MyWebApp/My/xyz/instructions/get, contentlength: -1
17:56:11.489 [http-apr-9090-exec-28] DEBUG waffle.apache.NegotiateAuthenticator - authorization: Negotiate YHwGBisGAQUFAqByMHCgMDAuBgorBgEEAYI3AgIKBgkqhkiC9xIBAgIGCSqGSIb3EgECAgYKKwYBBAGCNwICHqI8BDpOVExNU1NQAAEAAACXsgjiCQAJADEAAAAJAAkAKAAAAAYBsR0AAAAPUEFERVNLVE9QUVVPUlVNREVW, ntlm post: false
17:56:11.489 [http-apr-9090-exec-28] DEBUG waffle.apache.NegotiateAuthenticator - security package: Negotiate, connection id: 192.168.2.120:49692
17:56:11.528 [http-apr-9090-exec-28] DEBUG waffle.apache.NegotiateAuthenticator - token buffer: 126 byte(s)
17:56:11.530 [http-apr-9090-exec-28] DEBUG waffle.apache.NegotiateAuthenticator - continue required: true
17:56:11.530 [http-apr-9090-exec-28] DEBUG waffle.apache.NegotiateAuthenticator - continue token: oYIBHzCCARugAwoBAaEMBgorBgEEAYI3AgIKooIBBASCAQBOVExNU1NQAAIAAAASABIAOAAAABXCieIRmTQvO1r0QLAjCAIAAAAAtgC2AEoAAAAGAbEdAAAAD1EAVQBPAFIAVQBNAEQARQBWAAIAEgBRAFUATwBSAFUATQBEAEUAVgABABIAUABBAEQARQBTAEsAVABPAFAABAAeAFEAdQBvAHIAdQBtAEQAZQB2AC4ATABvAGMAYQBsAAMAMgBQAEEARABlAHMAawB0AG8AcAAuAFEAdQBvAHIAdQBtAEQAZQB2AC4ATABvAGMAYQBsAAUAHgBRAHUAbwByAHUAbQBEAGUAdgAuAEwAbwBjAGEAbAAHAAgAr+mVllZdzgEAAAAA
GET http://padesktop:9090/MyWebApp/My/xyz/instructions/get?unit=XXX11&data-type=BOAI&datefrom=2012-01-10&dateto=2012-02-01 HTTP/1.1
Authorization: Negotiate oXcwdaADCgEBoloEWE5UTE1TU1AAAwAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAABXCiOIGAbEdAAAADxD/qWi8cdQZHqoFVPcBDdGjEgQQAQAAAPUXp1AtIpqEAAAAAA==
Host: padesktop:9090
17:56:11.580 [http-apr-9090-exec-29] DEBUG waffle.apache.NegotiateAuthenticator - GET /MyWebApp/My/xyz/instructions/get, contentlength: -1
17:56:11.580 [http-apr-9090-exec-29] DEBUG waffle.apache.NegotiateAuthenticator - authorization: Negotiate oXcwdaADCgEBoloEWE5UTE1TU1AAAwAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAABXCiOIGAbEdAAAADxD/qWi8cdQZHqoFVPcBDdGjEgQQAQAAAPUXp1AtIpqEAAAAAA==, ntlm post: false
17:56:11.580 [http-apr-9090-exec-29] DEBUG waffle.apache.NegotiateAuthenticator - security package: Negotiate, connection id: 192.168.2.120:49692
17:56:11.629 [http-apr-9090-exec-29] DEBUG waffle.apache.NegotiateAuthenticator - token buffer: 121 byte(s)
17:56:11.631 [http-apr-9090-exec-29] DEBUG waffle.apache.NegotiateAuthenticator - continue required: false
17:56:11.631 [http-apr-9090-exec-29] DEBUG waffle.apache.NegotiateAuthenticator - continue token: oRswGaADCgEAoxIEEAEAAABDh+CIwTbjqQAAAAA=
17:56:11.638 [http-apr-9090-exec-29] DEBUG waffle.apache.NegotiateAuthenticator - logged in user: MyDomain\andez (S-1-5-21-3085694351-1625474162-905705579-1161)
17:56:11.791 [http-apr-9090-exec-29] DEBUG waffle.apache.NegotiateAuthenticator - roles: BUILTIN\Administrators, BUILTIN\Users, CONSOLE LOGON, Everyone, LOCAL, Mandatory Label\High Mandatory Level, NT AUTHORITY\Authenticated Users, NT AUTHORITY\INTERACTIVE, NT AUTHORITY\This Organization, PADesktop\WSS_ADMIN_WPG, MyDomain\ADL Viewers, MyDomain\Denied RODC Password Replication Group, MyDomain\Domain Admins, MyDomain\Domain Users, MyDomain\Public Folder Management, MyDomain\RemoteApp, MyDomain\Staff, MyDomain\andez, S-1-5-5-0-161840
17:56:11.829 [http-apr-9090-exec-29] DEBUG waffle.apache.NegotiateAuthenticator - session id:EDB24F55619BE3E42D81AF11EED78EE6
17:56:11.829 [http-apr-9090-exec-29] INFO waffle.apache.NegotiateAuthenticator - successfully logged in user: MyDomain\andez
My questions are:
How do I pass windows credentials from my client to the web server correctly?
Is this the way to implement Windows Authentication in JAX-RS in Tomcat?
Are there any other alternatives to using Windows Authentication with JAX-RS in Tomcat?
Am I expecting too much from RESTful web services and Windows Authentication just to automatically send the user credentials from a browser without a prompt and authenticating with Waffle/Active Directory?