Firefox asks for username/password on every HTTP request with Digest Authentication enabled on IIS6 - asp.net

I've recently enabled Digest Authentication on an intranet website/application I am creating for my company in ASP.NET.
The reason I have done so is because Windows Authentication seemed to only work for some users, and not for others. I could not figure out why nor do I know enough about IIS to try and trace the issue. After some trial and error, I found that digest authentication seemed to give me the behaviour that I wanted. That is: allow only users with a valid account on the domain to log in to the website with their credentials.
The problem now, is that Firefox (3+) seems to ask for the user to authenticate on every HTTP request sent to the server. This does not appear to occur in Internet Explorer (6+) or Chrome.
I've tried searching for solutions but I always arrive at dead-ends. I'll find a discussion about the issue, and every posted solution leads to a dead link...or it's on Experts Exchange and I don't have access to view to solution.
The issue appears to be related (from what I've read) to the way the different browsers send their authentication headers vs how IIS interprets them. I'm not sure what I can do to change this though? One of the solutions I had found mentioned writing an ISAPI filter to fix this, but of course the link to the finished filter was broken and I have no idea how to go about making one myself.
I've tried messing with the NTLM and other auth related strings in about:config to try and force Firefox to trust my server but that doesn't seem to work either.
From a few other sources I've read, it appears that everything should work if I switch back to Windows Authentication, but then I'm back at square one where the authentication would work only for some users and not others.
A solution for either problem would work for me, but I have very little information for the Windows Authentication issue. If someone could guide me through tracing the problem I'd gladly post more information for it as well.
Here are the URLs I've found discussing what seems like the same problem. (Sorry I couldn't make them all links, it wouldn't let me post otherwise)
support.mozilla.com/tiki-view_forum_thread.php?locale=pt-BR&forumId=1&comments_parentId=346851
www.experts-exchange.com/Software/Internet_Email/Web_Browsers/Mozilla/Q_24427378.html
channel9.msdn.com/forums/TechOff/168006-Twin-bugs-in-IIS-IE-unfair-competitive-advantage-EDIT-SOLVED/
www.derkeiler.com/Newsgroups/microsoft.public.inetserver.iis.security/2006-03/msg00141.html

This is a know bug in FF. See Advanced digest authentication works from Internet Explorer however we receive multiple authentication prompts on each GET request from fire fox
IE 6 had the same bug.A potential workaround would be to re-enable "old" Digest in IIS6:
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/1d6e22ac-0215-4d12-81e9-c9262c91b797.mspx?mfr=true
Currently, if the server send an opaque directive, the IE client will return this directive value as specified in the RFC. Unfortunately, for follow-on requests from the client where the nonce count is incremented (count 2 and beyond) the opaque directive value is not sent. This then fails authentication on the server and a 401 Unauthorized is returned. The IE client now requests the username and password for the new challenge and the file is retrieved.
This requires an additional round trip and the user is prompted for credential each time.
The RFC states that the opaque must always be sent on requests from the client.
The Digest implementation that IE6 is using is not RFC compliant (http://www.ietf.org/rfc/rfc2617.txt).
3.2.2 The Authorization Request Header
The values of the opaque and algorithm fields must be those supplied
in the WWW-Authenticate response header for the entity being
requested.
3.3 Digest Operation
A client should remember the username, password, nonce, nonce count and
opaque values associated with an authentication session to use to
construct the Authorization header in future requests within that
protection space.
Because the client is required to return the value of the opaque
directive given to it by the server for the duration of a session,
the opaque data may be used to transport authentication session state
information.
-------- Edit addition -----
Windows Authentication seemed to only work for some users, and not for others.
How did it fail? Did you enable impersonation?

Related

Why don't modern web browsers display the "realm" value for HTTP authentication anymore?

When hosting a website using HTTP Authentication, if the client has not authenticated, the server will send a 401 Unauthorized response, including a WWW-Authenticate header. An optional directive in this header is realm:
A string describing a protected area. A realm allows a server to partition up the areas it protects (if supported by a scheme that allows such partitioning), and informs users about which paricular username/password are required.
(emphasis mine)
Let's say www.example.com requires authorization and has configured a realm value of Test Area. Back in the day, most web browsers would display a login dialog when receiving such a response, and say something along the lines of "Authorization required. The site at www.example.com says 'Test Area'."
But (at least recent versions of) Chrome, Firefox, and Edge, now all just display a generic message, without including the realm value. Interestingly enough, IE still displays the realm value (screenshots below, all Windows 10 64bit):
Chrome (v93.0.4577.82)
Firefox (v92.0)
Edge (v93.0.961.52)
IE (v11.1411.18362.0)
I'm pretty sure Firefox and Edge used to display it. Chrome may have a while back but seems like it was the first to stop. Since all modern browsers aren't displaying it, I assume there's some reason why..?? I've search all over the internet, and can't figure it out. I have a use-case where it would be helpful to users to have the realm displayed, as it would make it clearer which particular credentials they need to use. I know that you can't force the browser to display it, but it's just annoying. However if there is a valid reason for it not being shown I'll accept that.
The reason is that this could be abused for phishing attacks, by putting some misleading message into the realm. The login dialog for http authentication is part of the trusted browser UI, and giving the server the opportunity to modify that UI - even by just displaying text - is a security risk.

HTTP POST from app.example.com to localhost: session cookie not sent

I have two Spring Web applications that work together. I'm running the first application from the IDE on localhost, while the second one is running in docker on app.127.0.0.1.nip.io.
The two applications interact indirectly through the users browser by redirecting and POSTing between the two apps. This is slightly similar to how an SP and an IdP work together in SAML2.
In my case, the first application on localhost is sending a 302 to the second application. After doing some work, the second application sends an HTML page with a form an JS code to autosubmit it, back to my first application on localhost. The HTML looks similar to this:
<form method=POST action="http://localhost:8080/some/path">
...
</form>
My first application is using Spring Session with a session cookie, and this works just fine. However, when the second application makes the browser POST the form, the browser does not send the session cookie with the POST request.
When both applications are running in docker under .127.0.0.1.nip.io, the cookie is sent.
I've tried to find any hint if this behaviour is expected, and what headers or other bits the applications could use to influence this.
At this point, this is mostly an annoyance while debugging, but I'm concerned that once the two applications will run on different FQDNs and/or different domains, the browsers will also block the cookie being sent.
I've tested this with current versions of Chrome and Firefox.
The problem is the new(ish) SameSite cookie policy that covers exactly this case: another application is POSTing to a host via HTTP. The default now is SameSite: lax, which does not allow sending the first-party cookie values on this request.
The solution is to allow the session cookie to be sent by specifying SameSite: none. Be aware however that this might create security vulnerabilities. For my application, this is not an issue, so I can allow the cookie to always be sent, and especially when I run my application in the debugger.
For the production deployment, I will be able to tighten this, since both applications will run under the same domain (a.example.com and b.example.com), and both will use TLS, so I can set the session cookie to SameSite: lax.
Here's a decent explanation: https://web.dev/samesite-cookies-explained/

Postman is not using cookie

I've been using Postman in my app development for some time and never had any issues. I typically use it with Google Chrome while I debug my ASP.NET API code.
About a month or so ago, I started having problems where Postman doesn't seem to send the cookie my site issued.
Through Fiddler, I inspect the call I'm making to my API and see that Postman is NOT sending the cookie issued by my API app. It's sending other cookies but not the one it is supposed to send -- see below:
Under "Cookies", I do see the cookie I issue i.e. .AspNetCore.mysite_cookie -- see below:
Any idea why this might be happening?
P.S. I think this issue started after I made some changes to my code to name my cookie. My API app uses social authentication and I decided to name both cookies i.e. the one I receive from Facebook/Google/LinkedIn once the user is authenticated and the one I issue to authenticated users. I call the cookie I get from social sites social_auth_cookie and the one I issue is named mysite_cookie. I think this has something to do with this issue I'm having.
The cookie in question cannot legally be sent over an HTTP connection because its secure attribute is set.
For some reason, mysite_cookie has its secure attribute set differently from social_auth_cookie, either because you are setting it in code...
var cookie = new HttpCookie("mysite_cookie", cookieValue);
cookie.Secure = true;
...or because the service is configured to automatically set it, e.g. with something like this in web.config:
<httpCookies httpOnlyCookies="true" requireSSL="true"/>
The flag could also potentially set by a network device (e.g. an SSL offloading appliance) in a production environment. But that's not very likely in your dev environment.
I suggest you try to same code base but over an https connection. If you are working on code that affects authentication mechanisms, you really really ought to set up your development environment with SSL anyway, or else you are going to miss a lot of bugs, and you won't be able to perform any meaningful pen testing or app scanning for potential threats.
You don't need to worry about cookies if you have them on your browser.
You can use your browser cookies by installing Postman Interceptor extension (left side of "In Sync" button).
I have been running into this issue recently with ASP.NET core 2.0. ASP.NET Core 1.1 however seems to be working just fine and the cookies are getting set in Postman
From what you have describe it seems like Postman is not picking up the cookie you want, because it doesn't recognize the name of the cookie or it is still pointing to use the old cookie.
Things you can try:
Undo all the name change and see if it works( just to get to the root of issue)
Rename one cookie and see if it still works, then proceed with other.
I hope by debugging in this way it will take you to the root cause of the issue.

Change Basic HTTP Authentication realm and login dialog message

I want to change the message that pops up during implementation of Basic Auth.The current default message is:
Server requires a username and password.
Something that would be more accurate for me is :
Server requires an Email and Password.
My problem is that i can't find or don't know where this message is set and if it can be changed. Most of the questions online are about Basic Auth implemention but this is not my problem -- i can implement it very fine. I just need a more accurate response for the user.
Here is how i force an authentication window using echo:
c.Response().Header().Set(echo.HeaderWWWAuthenticate, `Basic realm="Your Email is your Username"`)
return echo.ErrUnauthorized
NB: Only Firefox shows the realm message. Both Chrome and Opera do not.
This is not related to Go but actually to browser behaviour when receiving that header.
It seems Chrome/Chromium has a known issue with this related to the feature not considered secure by the development team, so I don't think you'd be able to fix it on your side unless you resort to some other authentication mechanism.
See here for more details:
https://bugs.chromium.org/p/chromium/issues/detail?id=544244#c32
Thanks for the responses but they were not satisfactory. I had to do some reading on this topic.
The correct answer is that the login prompt/dialog is a response built into the user-agent/browser and cannot be changed by the server. This also explains why some browsers show realm while others don't.
According to Wikipedia Basic access authentication all the server does is:
When the server wants the user agent to authenticate itself towards the server, it must respond appropriately to unauthenticated requests.
Unauthenticated requests should return a response whose header contains a HTTP 401 Unauthorized status[4] and a WWW-Authenticate field.[5]
The WWW-Authenticate field for basic authentication (used most often) is constructed as following:
WWW-Authenticate: Basic realm="User Visible Realm"

Can the HTTP response header Authorization be managed from the server?

I'm playing with HTTP Basic Authorization. As we all know, when a client gets a 401 error on requesting a page, the client must collect authorization credentials from the users (typically in the form of a pop-up window).
Subsequent requests for resources under that part of the URL will be accompanied by "Authorization: Basic [hash]" where [hash] is the username/password mashed together and hashed.
What I'm interesting in is getting the client to not send the Authorization header even when requesting a resource that previously asked for it.
Three important questions:
Is this possible?
If possible, does this violate the HTTP/1.1 standard (I'm unclear that this case is covered by the spec)?
What browser support this?
Thanks for your time, Internet.
UPDATE: Apparently, this is an apache FAQ and I am SOL. Still, if you've got thoughts on this question, I'd love to hear about it. Thanks.
I don't think this is possible. The authenticated session lasts until the user shuts the browser window, and the browser will keep on blindly passing the credentials with each request under the same path.
Is there any specific reason why you want this functionality?
You can set the user and password in the URL:
http://user:password#example.com
If you use this syntax, the browser will generate the header for you.

Resources