HTTP Basic Authentication - what's the expected web browser experience? - basic-authentication

When a server allows access via Basic HTTP Authentication, what is the experience expected to be in a web browser?
Ignoring the web browser for a moment, here's how to create a Basic Auth request with curl:
curl -u myusername:mypassword http://somesite.example
But what about in a Web Browser? What I've seen on some websites, is I visit the URL, and then the server returns response code 401. The browser then displays a username/password prompt.
However, on somesite.example, I'm not getting an authorization prompt at all, just a page that says I'm not authorized. Did somesite not implement the Basic Auth workflow correctly, or is there something else I need to do?

To help everyone avoid confusion, I will reformulate the question in two parts.
First: "how can make an authenticated HTTP request with a browser, using BASIC auth?".
In the browser you can do a HTTP basic auth first by waiting the prompt to come, or by editing the URL if you follow this format: http://myusername:mypassword#somesite.example
NB: the curl command mentionned in the question is perfectly fine, if you have a command-line and curl installed. ;)
References:
https://en.wikipedia.org/wiki/Basic_access_authentication#URL_encoding
https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax
https://www.rfc-editor.org/rfc/rfc3986#page-18
Also according to the CURL manual page https://curl.haxx.se/docs/manual.html
HTTP
Curl also supports user and password in HTTP URLs, thus you can pick a file
like:
curl http://name:passwd#machine.domain/full/path/to/file
or specify user and password separately like in
curl -u name:passwd http://machine.domain/full/path/to/file
HTTP offers many different methods of authentication and curl supports
several: Basic, Digest, NTLM and Negotiate (SPNEGO). Without telling which
method to use, curl defaults to Basic. You can also ask curl to pick the
most secure ones out of the ones that the server accepts for the given URL,
by using --anyauth.
NOTE! According to the URL specification, HTTP URLs can not contain a user
and password, so that style will not work when using curl via a proxy, even
though curl allows it at other times. When using a proxy, you _must_ use
the -u style for user and password.
The second and real question is "However, on somesite.example, I'm not getting an authorization prompt at all, just a page that says I'm not authorized. Did somesite not implement the Basic Auth workflow correctly, or is there something else I need to do?"
The curl documentation says the -u option supports many method of authentication, Basic being the default.

Have you tried?
curl somesite.example --user username:password

You might have old invalid username/password cached in your browser. Try clearing them and check again.
If you are using IE and somesite.example is in your Intranet security zone, IE may be sending your Windows credentials automatically.

WWW-Authenticate header
You may also get this if the server is sending a 401 response code but not setting the WWW-Authenticate header correctly - I should know, I've just fixed that in out own code because VB apps weren't popping up the authentication prompt.

If there are no credentials provided in the request headers, the following is the minimum response required for IE to prompt the user for credentials and resubmit the request.
Response.Clear();
Response.StatusCode = (Int32)HttpStatusCode.Unauthorized;
Response.AddHeader("WWW-Authenticate", "Basic");

You can use Postman a plugin for chrome.
It gives the ability to choose the authentication type you need for each of the requests.
In that menu you can configure user and password.
Postman will automatically translate the config to a authentication header that will be sent with your request.

Related

Making an HTTP request with a blank user agent

I'm troubleshooting an issue that I think may be related to request filtering. Specifically, it seems every connection to a site made with a blank user agent string is being shown a 403 error. I can generate other 403 errors on the server doing things like trying to browse a directory with no default document while directory browsing is turned off. I can also generate a 403 error by using a tool like Modify Headers for Google Chrome (Google Chrome extension) to set my user agent string to the Baidu spider string which I know has been blocked.
What I can't seem to do is generate a request with a BLANK user agent string to try that. The extensions I've looked at require something in that field. Is there a tool or method I can use to make a GET or POST request to a website with a blank user agent string?
I recommend trying a CLI tool like cURL or a UI tool like Postman. You can carefully craft each header, parameter and value that you place in your HTTP request and trace fully the end to end request-response result.
This example straight from the cURL docs on User Agents shows you how you can play around with setting the user agent via cli.
curl --user-agent "Mozilla/4.73 [en] (X11; U; Linux 2.2.15 i686)" [URL]
In postman its just as easy, just tinker with the headers and params as needed. You can also click the "code" link on the right hand side and view as HTTP when you want to see the resulting request.
You can also use a heap of hther HTTP tools such as Paw and Insomnia, all of which are quite well suited to your task at hand.
One last tip - in your chrome debugging tools, you can right click the specific request from the network tab and copy it as cURL. You can then paste your cURL command and modify as needed. In Postman you can import a request and past from raw text and Postman will interpret the cURL command for you which is particularly handy.

wget won't download files I can access through browser

I am an amateur historian trying to access newspaper archives. The server where the scans are located "works" using an outdated tif viewer that doesn't seem to actually work at all anymore. I can access the files individually in chrome without logging in, but when I try to use wget or curl, I'm told that viewing the file is unauthorized, even when I use my login info, and even when using my cookies from chrome.
Here is an example of one of the files: https://ulib.aub.edu.lb/nahar/images2/7810W2/78101001.TIF
When I put this into chrome, it automatically downloads the file even though I cannot access the directory itself, but when I use wget, I get the following response: "401 unauthorized Username/Password Authentication Failed."
This is the basic wget command I'm using (if I can get it to work at all, then I'll input a list of the other files):
wget --no-check-certificate https://ulib.aub.edu.lb/nahar/images2/7810W2/78101001.TIF
I've tried variations with and without cookies, with a blank user, with and without login credentials, As I'm sure you can tell, I'm new to this sort of thing but eager to learn.
From what I can see, authentication on your website is done with HTTP basic. This kind of authentication is not using HTTP cookies, it is using HTTP Authorization header. You can pass HTTP basic credentials to wget with the following arguments.
wget --http-user=YourUsername --http-password=YourPassword https://ulib.aub.edu.lb/nahar/images2/7810W2/78101001.TIF

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"

HTTP Preauthorization

At http://localhost/tmp/ I have a form that asks for the user and password (authentication).
After the user posts (hits OK) I want to redirect the user to http://localhost/test/ which uses Apache's Basic AuthType. Happens that the user and password just typed in the form are exactly the credentials to authenticate at http://localhost/test/
What I want is the solution so that the user is not asked for the password in the second address. So far I was able to pass the 'Authorization: Basic "base64_encoded user and password"' with CURL (using GET), and get the response I want (contents of test/index.html, for example). However, that's curl getting the info instead of my browser redirecting there with preauthorization. That is, if I type http://localhost/test/ in the address bar it asks for the password again. Any ideas? Any clarification needed?
The problem is that the authorization state is maintained in the browser, and there's no real way to tell the browser it's authorized.
Most systems rely on a Cookie system, but BASIC/DIGEST HTTP AUTH are HTTP headers. So, only the browser can set those.
I should say, for normal every day requests -- you might (I'm not sure) be able to set the headers in an XHR.
Could you simply set the form submit location to the redirect destionation http://localhost/test/ and take care fo the authentication here?
As an aside, Fiddler is a great tool for debugging this sort of thing
Will's answer points you in the right direction.
In IE at least, it works to send an XHR request (to some throwaway page) with the Username/Password parameters (in the Open() call) set. Doing that will cache this username and password internally for the browser session, and so when you subsequently visit other pages on the server, the authentication SHOULD automatically happen for those pages.
I can't say if this trick works in other browsers or not.

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