Passing basic auth credentials when navigating in browser - http

The situation is:
User is on site http://foo.com/ in one browser tab
This site needs to have a link/button that will open https://bar.com/ in a new tab
https://bar.com/ uses basic auth, and foo.com wants to automatically pass those credentials, such that the user is not prompted by the browser.
The obvious answer here is to pass the creds in the URL, e.g. https://user:password#bar.com. Unfortunately, this good old syntax doesn't work in all browsers (doesn't work in the latest IE).
I'm looking for an alternative that would work across all major browsers. e.g. potentially something along these lines:
The foo.com page builds the Authorization header (by base 64 encoding the creds, ...)
Somehow inject those headers into the request that gets sent to https://bar.com/, such that the request gets authorized with no user prompting.

Even if you are able to achieve sending the credentials to the site on the first request, unless the browser knows the contents of the credentials, it will have to prompt the user again for these credentials if the user navigates to another page on that same (bar.com) site that is protected by basic authentication.
If you have control over the bar.com site, then you might consider an alternative authentication scheme that uses a token generated by foo.com, which bar.com then interprets and, if valid, initializes its session to look at a cookie instead of requiring basic authentication for future requests.
Take a look at this question and this one.

Related

How to add login credentials to URL

I tried https://myserver.com/~username=username&password=mypassword but it doesn't work.
Can you confirm that it's possible to pass the user/pass via HTTPs parameters (GET or POST)?
Basically, I want to access this link https://www.globalnorm.net/gn/doc.php?name=ASTM%20F%202638:2012-00&erx=0 (but I need to authenticate ) How can pass my username and password in URL?
The standard method to pass basic authentication to web servers is to use a url of the form:
http://user:password#domain.com/
Web servers do not expect basic authentication in the query parameters. You can, of course, implement your own authentication using query parameters / HTTP headers or any other method.
Update
The specific URL you had supplied redirects to https://www.globalnorm.net/login.php?ecd=S&info=nosessionorcookie&doc=....
The login path does not return the header WWW-Authenticate which is used to indicate that basic authentication is supported. So no point in trying HTTP basic authentication.
This specific login page seems to expect a POST request to /login.php with USR, PAS parameters. The answer will probably include a cookie which is later used to authenticate with the server.
There seems to be some controversy about whether or not browsers have dropped the feature, and/or whether the feature is deprecated. But unless your browser has in fact dropped the feature, then as noted in #nimrodm's answer above, you can specify a url with basic authentication as
http://user:password#domain.com/
However, you really should not use http protocol, since that will send the credentials in clear text. Instead, just use:
https://user:password#domain.com/
Note that you must urlencode special characters in the user or password fields (I frequently use '#' in my passwords, so those must be written as '%40').
The browser extracts the credentials, and passes them to the server in an Authorization header:
Authorization: Basic credentials
where the credentials are simply the (url-decoded) string "username:password" as written in the url, but base64-encoded. But since the https connection is encrypted, the header is encrypted and the credentials are not exposed outside the browser.
I think the whole issue about removing support or deprecating the feature was based on the security implications of specifying the credentials using http protocol. But with the availability of free ssl certificates, and the push for "ssl everywhere", that no longer seems like much of a problem these days.
Of course there's also the issue of how much good passing credentials this way does you. Many or most applications that require login expect to get the credentials from a form the user fills out and sends with a POST request. The application would have to be written to check each request for an Authorization header, and if present, process the credentials the same way they would if they had been specified by a POST of a filled-out login form.
Applications that expect HTTP basic authentication generally are built with that requirement built into the server configuration, e.g. using Apache directives along theses lines:
<Directory "/htdocs/protected">
AuthName "Registered User"
AuthType Basic
AuthUserFile /lib/protected.users
require valid-user
</Directory>
Where the file /lib/protected.users is a file of encrypted usernames and passwords generated by the Apache utility program htpasswd. With this configuration, any request for resources below /htdocs/protected is automatically checked by Apache for an Authentication header. If the request has no such header, or the credentials specified in the header do not match one of the pairs of usernames and passwords in /lib/protected.users, then the server responds with a 401 Unauthorized status and a header:
WWW-Authenticate Basic realm="Registered User"
Note that the realm value "Registered User" is the AuthName value from the Apache configuration. The browser handles this response by displaying a prompt requesting username and password, with the value of the realm contained in the prompt to give the user a hint as to what particular username and password is required.
Browsers have to treat the credentials specially anyway to convert them to an Authorization header, and so they also cache them and send them each time with requests to the same endpoint, like sending cookies. If they didn't do this, then the user would have to supply them on each subsequent url specifying that endpoint to avoid getting prompted.
Hope this helps.
The web server doesn't care about anything past the "?". This data gets sent to the application.
If you're actually authenticating to the application you would need to check the app's documentation for the correct parameter names.
In the past, you could supply the username:password#domain in the URL, but this has been disabled in many recent browsers because of security risks.
Currently, the only way I'm aware of to do an auto login is to set a basic auth header and do a form post, however you'll be better off to use a library that already knows how to do it, since the fields need to be encoded properly to work.
If I am correct in my assessment, the question is Can you confirm that it's possible to pass the user/pass via HTTPs parameters (GET or POST)?
Here is a snippet of code that I am using to send username and password as parameters to a GET call. Hope it helps.
$('#button').click(function () {
var username = $('#username').val();
var password = $('#password').val();
window.location.href = '#Url.Action("DesiredAction")?username=' + username + '&password=' + password;
});

Mixing NTLM with Forms Authentication in IE (Empty POST issue)

Our ASP.NET application is hosted in IIS 7.5 and has the following setup:
main site is hosted under root IIS folder accessible with http://siteurl (1)
we have a separate app in the same AppPool hosted under http://siteurl/Intranet (2)
Main app (1) has Anonymous Authentication enabled along side Forms Authentication (url: siteurl/loginform).
Second app (2) has Integrated Authentication (NTLM).
The login procedure works as following:
User goes to siteurl first
User gets redirected to /Intranet to check integrated auth
If integrated is accepted user gets redirected back with proper auth cookies to siteurl and gets access to the site
If integrated fails user gets redirected to siteurl/loginForm to manually fill in credentials
We have some issues with Internet Explorer (8, 9, 10) that refuses to submit the form data at step 4. It appears to be a known behavior that IE will not POST content to an unauthenticated site once the NTLM negotiation started for that session. I have considered some workarounds for this:
store credentials in a cookie (with JS) and on the server if the POST content has 0 length try to check the cookie values. delete the cookie afterwards
send credentials using GET instead of POST (ugly as we need to make sure the user does not see his just posted password in the browser address bar)
Provide a link to the user to open a new tab and continue the auth process in a separate browser session (this seems to work as IE will happily send POST data from a second tab)
Are there any other options we might have to get around this issue?
From the above 3 which one would be preferable and what unconsidered pitfalls we might encounter?
I wrote about this issue here: http://blogs.msdn.com/b/ieinternals/archive/2010/11/22/internet-explorer-post-bodies-are-zero-bytes-in-length-when-authentication-challenges-are-expected.aspx
Your question omits important information which makes it hard to troubleshoot. You should never see the problem described with the literal URLs you've used, because IE uses protection spaces to decide whether a site is going to demand credentials via a HTTP/401 and example.com/ and example.com/foo/ are different protection spaces.
It would be very helpful if you could share a Fiddler log of this scenario for better troubleshooting.

How can webservers detect replayed login attempts?

I found a strange thing when i'm coding a net-spider to a specific website.
I used fiddler and chrome(as well as other web-browsers) to log-in a website(HTTP, not https) and get all package(as well as the cookie) that sent and received:(
first package 'Get' to request the log-in page and the cookie, then use the cookie received to request verification code and some other pics. and then send login request with userid, password and verification code to server and server response with correct info)
Then I log-out and Clear all Cache and Cookie and use Fiddler to Relay(Simulate) the whole process (Since I know all packages' format that i should send): request the log-in page to get cookie, use the cookie to request all pics( auth code image included), and then use the cookie and auth code to request login(userid and password are correct)...but failed.
I'm sure the failure is not caused by invalid userid or password or auth code, and i believe there is nothing special on the front-end(html,script are checked), but it puzzled me a lot how can the server tell i used browser or not in back-end..
I'm not request anybody to solve the specific problem. i'm just wanna know DOES ANYONE HAS HAD SIMILAR PROBLEM i described?
the specific website is not important and i must say the whole practice is completely harmless! i'm not doing any hacking stuff, on the contrary it will help some people.
======================================================
I've finally figured out the reason: the log-in page has a hidden input() and i carelessly overlooked that since its value looks almost the same every time. Web server can not detect replayed log-in attempts if we simulated all necessary HTTP request packages.
Thank you guys~
Servers cannot magically tell whether they're talking to Fiddler or not.
If Fiddler and your client are sending the exact same requests, that means that the server in question is using a "one time token" (sometimes called a nonce) in its login form. If the server ever sees the same token again, it rejects the logon. Sometimes the nonce isn't sent directly, and is instead used in the computation of a "challenge-response" as occurs in authentication protocols like NTLM. In other cases, the nonce is a CAPTCHA, which helps prevent you from using a bot to automatically log in to a site like this.
Unless you can share more details of the target site (or a SAZ file of the login process), it's unlikely that folks will be able to help you.

Regarding the workings of cookies in sign in systems on the web

I was using Fiddler see on-the-field how web sites use cookies in their login systems. Although I have some HTTP knowledge, I'm just just learning about cookies and how they are used within sites.
Initially I assumed that when submitting the form I'd see no cookies sent, and that the response would contain some cookie info that would then be saved by the browser.
In fact, just the opposite seems to be the case. It is the request that's sending in info, and the server returns nothing.
When fiddling about the issue, I noticed that even with a browser cleaned of cookies, the client seems to always be sending a RequestVerificationToken to the server, even when just looking around withot being signed in.
Why is this so?
Thanks
Cookies are set by the server with the Set-Cookie HTTP response header, and they can also be set through JavaScript.
A cookie has a path. If the path of a cookie matches the path of the document that is being requested, then the browser will include all such cookies in the Cookie HTTP request header.
You must make sure to be careful when setting or modifying cookies in order to avoid XSS attacks against your users. As such, it might be useful to include a hidden and unique secret within your login forms, and use such secret prior to setting any cookies. Alternatively, you can simply check that HTTP Referer header matches your site. Otherwise, a malicious site can copy your form fields, and create a login form to your site on their site, and do form.submit(), effectively logging out your user, or performing a brute-force attack on your site through unsuspecting users that happen to be visiting the malicious web-site.
The RequestVerificationToken that you mention has nothing to do with HTTP Cookies, it sounds like an implementation detail that some sites written in some specific site-scripting language use to protect their cookie-setting-pages against XSS attacks.
When you hit a page on a website, usually the response(the page that you landed on) contains instructions from the server in the http response to set some cookies.
Websites may use these to track information about your behavior or save your preferences for future or short term.
Website may do so on your first visit to any page or on you visit to a particular page.
The browser would then send all cookies that have been set with subsequent request to that domain.
Think about it, HTTP is stateless. You landed on Home Page and clicked set by background to blue. Then you went to a gallery page. The next request goes to your server but the server does not have any idea about your background color preference.
Now if the request contained a cookie telling the server about your preference, the website would serve you your right preference.
Now this is one way. Another way is a session. Think of cookies as information stored on client side. But what if server needs to store some temporary info about you on server side. Info that is maybe too sensitive to be exposed in cookies, which are local and easily intercepted.
Now you would ask, but HTTP is stateless. Correct. But Server could keep info about you in a map, whose is the session id. this session id is set on the client side as a cookie or resent with every request in parameters. Now server is only getting the key but can lookup information about you, like whether you are logged in successfully, what is your role in the system etc.
Wow, that a lot of text, but I hope it helped. If not feel free to ask more.

How to authenticate users across domains using ASP.NET and iframes?

I am doing an ASP.NET website for a client, who wants to make their reports page available via IFRAME on other "reseller" websites.
The reseller websites are providing the same service with different branding.
I need to avoid, where I can, requiring them to implement any code on their webserver to enable this - hence using iframes.
A user would log in to the reseller website, load a page which contains an iframe, which in turn loads the report at the primary site.
As parameters, we would send the reseller id, and their username.
We can use SSL server certificates, but not any federated login (like OpenId) - a business choice of the client.
The question is, how does the primary site verify that the report page really is being requested by the user who loaded the page from the reseller?
In other words, how to authenticate the user across domains, without requiring the reseller to implement code..
Any thoughts would be much appreciated!
Your login form can use some javascript to post the login form to a hidden iframe (you can't use an XMLHTTPRequest because of cross domain security concerns) for each domain that you require a login for.
Be sure to redirect your iframe back to the original domain or you won't be able to fetch the login status out of the iframe due to cross-domain security.
The final trick for IE support is to flip the evil bit and add
P3P: CP="CAO PSA OUR"
to your HTTP response headers. Which tells the browser "I am not going to do anything bad, honest".
http://support.microsoft.com/kb/323752
http://www.w3.org/P3P/
I see no satisfactory way to do this without implementing any code on the reseller site.
Instead, I would require them to send an HTTPS request from the reseller webserver to the primary webserver, passing a unique secret key to identify themselves, as well as the username of their logged-on user.
Once verified on the primary site, this key would then serve as authentication for the reseller, and by extention, their logged-on user.
The response of this request would contain a html fragment string, which the reseller can inject into any page.
This fragment would contain an iframe, which, in turn, would load the report for the logged-on user directly from the primary site, using their username.
This report content would contain a reference to a reseller-specific stylesheet.
With this approach I would say HTTPS is not required in the browser, since both the reseller and their user is authenticated, and if that process happened over HTTPS, we can assume there is no eavesdropper.
In the case where the secret key or the user password got compromised, HTTPS from the browser would make no difference anyway.
I might be missing something, but if the client is authenticated against your server, then it will still be authenticated if you view it through an iframe.
For example, create an HTML page on your server with an iframe to gmail. As long as you're authenticated against gmail in your browser you will see your inbox in that page...

Resources