| # | Result | Protocol | Host | URL | Body | Caching | Content-Type | Process | Comments | Custom |
|---|---|---|---|---|---|---|---|---|---|---|
| 3 | 401 | HTTP | localhost | /MyRestApplication/articles | 5 418 | private | text/html; charset=utf-8 | iexplore:1312 | ||
| 4 | 401 | HTTP | localhost | /MyRestApplication/articles | 341 | text/html; charset=us-ascii | iexplore:1312 | |||
| 5 | 401 | HTTP | localhost | /MyRestApplication/articles | 5 428 | private | text/html; charset=utf-8 | iexplore:1312 | ||
| 6 | 401 | HTTP | localhost | /MyRestApplication/articles | 341 | text/html; charset=us-ascii | iexplore:1312 | |||
| 7 | 401 | HTTP | localhost | /MyRestApplication/articles | 5 428 | private | text/html; charset=utf-8 | iexplore:1312 | ||
| 8 | 401 | HTTP | localhost | /MyRestApplication/articles | 341 | text/html; charset=us-ascii | iexplore:1312 |
Disable “integrated authentication” in IIS and it won’t add the other headers.
You can prioritize them but as IIS adds no q= there’s nothing you can do to get basic over Negotiate. IE is free to do as it wish in selecting which authentication scheme to use anyway, as long as the server advertise it.
No no no. The way HTTP auth works is that you can have multiple authentication types that are available. OpenRasta has Basic, IIS has its own Basic, and iwndows integrated (aka negotiate and ntlm). If you *disable* windows auth in IIS, then the client will pick the authentication provided by OpenRasta. If you *enable* windows auth in IIS, then IIS will do the authentication and OpenRasta has no control over that at all.
If you disable win auth in IIS then the problem goes away. If you enable win auth in IIS, then IE will use that and you need to make sure users have accounts in whatever direcetory service your IIS box uses to authenticate windows users (usually your windows server).
So there’s not much to fix in what you’ve written except for removing the option from IIS.
If you don’t protect the xap file then no, you don’t need window sauthetnication or any authentication to serve that xap file. If you require authentication on the xap file, then it’s the same as for your service.
There’s really no infinite recursion, there’s an infinite access attempt from the client after multiple unsuccessful attemps, which is a bug in the client code and you’ll have to take it with whoever wrote the client or the underlying http connection (which may be any of Silverlight’s http client, the browser client, the chrome frame plugin or the code making use of that code randomly repeating over and over again).
Either OR doesn’t authorize the request, or IIS doesn’t authenticate because it doesn’t know the credentials or something.
You can check the reason for the 401 in the IIS logs, it’ll tell you the subcode. You can check the openrasta log if you enable logging (which you can get in the debugger if you’re attached, or configure through trace sources) and it’ll tell you if it’s responsible for the response (I don’t think OR even gets called at all from the shape of your log file).
Let me try to explain based on your logs:
1. Client sends unauthenticated request. OpenRasta sees that proper authorization is not available (user is authenticated) and returns a 401. IIS adds its own “available authentication scheme” on top of the OR ones
2. Client choses the IIS authentication scheme (as it’s allowed to do) and reissue the request. IIS reads that and authenticates the user, creating an IPrincipal that OpenRasta will now use to decide if the user is authorized for the method. OpenRasta sees that the windows user in question *does not* have the correct authorization for that resource, and issues another challenge.
3. Client receive the 401, choses the IIS authentication scheme (as it’s allowed to do) and reissue the request. IIS (see point 2).
4. Rinse, repeat, advitam eternam.
As I expressed before, OpenRasta is doing the right thing. IIS is doing the right thing. The client *may* be doing the right thing but I doubt it:
10.4.2 401 Unauthorized
The request requires user authentication. The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource. The client MAY repeat the request with a suitable Authorization header field (section 14.8). If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials. If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user SHOULD be presented the entity that was given in the response, since that entity might include relevant diagnostic information. HTTP access authentication is explained in "HTTP Authentication: Basic and Digest Access Authentication" [43].
In effect, either the client (the http lib in use) does not understand the whole point of not restarting if it’s the same challenge, or maybe IIS returns a different challenge everytime, which I don’t know about because only Microsoft implements that stuff and no one cares much for implementing it independently on the server.
Now, that’s not even half of the problem, because if you look at your log files you’ll see that the first and the second responses don’t come from the same server component: The first response comes from IIS (because it was an unchallenged request, OR replied, and IIS didn’t involve the http listener very much). But because the http listener underneath all sees a perfectly well authenticated connection (both because the client doesn’t understand that a positive response in a WWW-Authenticate combined with a 401 should still fail those credentials, and beause the host is dumb enough to continue with an authenticated response even though a higher level framework specifically said it was a 401), everyone underneath gets very confused, as they are very much used to owning everything and having only dim-witted frameworks built on top of them.
Sooo all this to say: the client is not doing the right thing, the http.sys component is not either, IIS7.5 itself has little to do with it all and OpenRasta has absolutely no way to influence any outcome in that environment, as the IIS components have handled the whole shebang of authentication without asking anyone and without listening to anyone.
So you have two solutions. Either you switch to windows authentication and you leave OpenRasta with authorizing strictly (aka return a 403 in the knowledge that no browser using NEGOTIATE will ever ask you for different credentials, which is the whole point of http authentication being a challenge/response system, but I disgress), or you disable authentication in IIS so OpenRasta can do its job. There are no other alternatives.
Hmm. Either OR was called and the user was the windows authenticated one, or the user in question is not authorized and then it’s IIS / http.sys that answers before dispatching to us. Either way it won’t work, that’s what I’m trying to get to :)
I’m not sure how to explain it any further. Whenever IIS takes over authentication, we have no control over what the heck is going on, because that’s how MS built their infrastructure.
If things end up using NEGOTIATE, IIS does all the work.
If the client is providing a specific username and password, then negotiate will authenticate that against Active Directory and authenticate or not, based on whatever credentials are available on the Active Directory server.
If you don’t get authenticated (because the client sends credentials that only exist in the basic authentication in OpenRasta, and there are no matching username/password in active directory), then you get a 401, and the client re-issues over and over again (a bug in the client code).
If you do get authenticated, IIS retrieves the groups your windows account (the one you authenticated for with a username and password) and creates an IPrincipal for asp.net that tells you what windows groups that user is member of. This may or may not (and probably doesn’t) match what your authentication provider in OpenRasta would respond with.
That’s the authentication part, aka “who the hell are you and what groups are you part of”, and is represented by the IPrincipal and IIdentity interfaces part of .net. OpenRasta just assume that if you’re not anonymous, you have been authenticated by something else and use whatever IPrincipal/IIdientity comes from the hosting environment (IIS).
When *authorization* kicks in, which is *what are you allowed to see*, then OpenRasta use the IPrincipal/IIdentity couple to check if you’re allowed to do something (such as access a protected resource). That’s based on the groups AD came back, and theres nothing we can do about what authenthication was done by the underlying platform.
Let me reformulate. There is no way we can change what happens before OpenRasta gets hit, and the fix to prevent that is to configure the IIS properly to not allow IIS to do the authentication. What is it that you’re trying to “fix” that is not already fixed by the fix?
From: open...@googlegroups.com [mailto:open...@googlegroups.com] On Behalf Of Mark Kharitonov
Sent: 28 June 2011 22:25
To: open...@googlegroups.com
Subject: Re: [openrasta] Accessing a resource with basic authentication when hosted in IIS 7 from Internet Explorer (9) results in an infinite recursion - please help.
I am new to the world of web services and I am trying to understand how the things work. Now, here is what I have:
· A resource without any authentication is served just fine with IIS/Cassini on the server side and IE/Firefox - on the client.
· A resource with basic authentication is served just fine with IIS/Cassini on the server side and Firefox - on the client.
· A resource with basic authentication is served just fine with Cassini on the server side and IE/Firefox - on the client.
· A resource with basic authentication is served just fine with IIS on server side and IE - on the client, provided windows authentication is disabled for the particular ASP.NET application in IIS.
· The problematic scenario is when:
o A resource with basic authentication is served
o IIS on server side
o IE on client side
o Windows authentication is enabled for the particular ASP.NET application in IIS.
Right, so I’ve had to refresh myself on how SPNEGO works (http://tools.ietf.org/html/rfc4559).
What you’re seeing is perfectly normal and the infinite loop is unavoidable.
The back and forth of GET / 401 is normal until the whole negotiation and exchange is done between client and server. At that point, IIS let the request go through as it considers the authentication to have succeeded. At that point, OR may receive the request with the principal provided by IIS (your switch from 7 to 2), and that hasn’t got the right permissions (as it’s a domain account, not the account you return from your credential provider in OR), so OR re-issues a 401, and IIS gets confused and re-initiate the negotiation.
There’s just no way to prevent this from happening, a new challenge will always be initiated when someone in the pipeline is saying the credentials presented don’t have access. In your case, that’s always hadnled by IIS, unless you disable windows authentication on that application.
I don’t think there’s any failing there, it’s just an awkward thing that is happening. I still think that considering, the client is the one with a bug as it doesn’t detect infinite redirects to start with.
From: open...@googlegroups.com [mailto:open...@googlegroups.com] On Behalf Of mark Kharitonov
Sent: 29 June 2011 14:43
To: open...@googlegroups.com
Subject: Re: [openrasta] Accessing a resource with basic authentication when hosted in IIS 7 from Internet Explorer (9) results in an infinite recursion - please help.
First of all, I have found another way around this issue. Instead of disabling Windows Authentication in IIS, one can disable it in IE - http://blog.super-networking.net/2008/02/internet-explorer-enable-integrated-windows-authentication/.
Next, I will try to explain what I do not understand. I know the following facts:
1. IE tries to negotiate with IIS between NTLM and Kerberos. This is the meaning of the Negotiate http authentication scheme.
2. Everything happens on my local machine, which does not have Kerberos.
3. This is the first web app hosted on my local IIS requiring authentication, so I have never encountered these issues before.
4. I am logged in with my domain account - no problems in this department.
5. The loop cycle goes like this:
1. IE requests a page from OR. No Authorization headers are given.
2. OR fails the request with 401 demanding basic authentication
3. IIS adds on it two more WWW-Authenticate headers demanding Negotiate and NTLM authentication
4. IE (having Integrated Windows Authentication enabled) picks the Negotiate scheme and responds with some authentication data.
5. IIS responds to it with yet another Negotiate authentication data, without notifying OR at all. The status is still 401.
6. At this point IE repeats the request (1), only this time it includes the Authorization: Negotiate header with some yet another data.
7. Goto (2)
I’d expect that too. What’s HttpContext.Current.User containing?
Is that the ICommunicationContext one? what about the one on HttpContext.Current.User?
From: open...@googlegroups.com [mailto:open...@googlegroups.com] On Behalf Of mark Kharitonov
Sent: 29 June 2011 15:53
To: open...@googlegroups.com
I see.
Well I’m not sure I know why the identity is not flowing then post-negotiation.
Wonder if the credential readers don’t try and reset them when the sceme is unkown, although that seems unlikely. Let me have a check.
From: open...@googlegroups.com [mailto:open...@googlegroups.com] On Behalf Of mark Kharitonov
Sent: 29 June 2011 16:14
To: open...@googlegroups.com
I checked and there is nothing of the sort.If it’s a local server that you connect to, and there are no proxies, and the request goes back to OR the second time around, something is not reading the credentials properly on the asp.net side, and I would have no idea why.
I’d suggest doing an empty web application, protect it with windows integrated auth, and try to get some file, that may help you diagnose which config switch in IIS you may be hitting
I'm not sure in this case that you should be adding an auth scheme, as technically you're not actually doing authentication, you're doing authorization after authentication has been done. With this, OpenRasta will think it's handling authentication, and will add the negotiate scheme to the list of potential schemes it can handle, which would be a bit iffy.
I'd suggest instead to be writing a pipeline contributor and simply changing the Identity on the ICommunicationContext.User property to an instance of GenericPrincipal.
OK, I will try to introduce a dedicated pipeline contributor for that.
As for the code itself: The check on the authentication type shouldn't return a Failed when it doesn't work, as you've not actually failed authentication, it's just an authetnication you don't know about.
Furthermore, take a dependency on ICommunicationContext rather than HttpContext, or you'll be stuck forever on asp.net as a hosting environment.
No can do. I tried that first, but ICommunicationContext.User is still null at that time. I do not like the dependency on asp.net, though, so I will be happy to get another suggestion.
As for getting the username from an IPrincipal, ther'es already an IIdentity that gives you just that, so I'd suggest removing IMapPrincipalToUser, unless you have some custom code in there instead of just using windows accounts.
There is a difference. Basic authentication defines application users, whereas WindowsIdentity corresponds to OS accounts. The application logic revolves around application users and groups, so OS accounts must be mapped somehow to application users - enter IMapPrincipalToUser.
Your dependency registrations also register your scheme aas a singleton, but has a depenndency on something registered as a transient, which is going to give you not what you expect.