421

I'm making a REST-API and it's straight forward to do BASIC auth login. Then let HTTPS secure the connection so the password is protected when the api is used.

Can this be considered secure?

Anders
  • 65,052
  • 24
  • 180
  • 218
Morten
  • 4,363
  • 3
  • 15
  • 7
  • 7
    Yes, the http user/pass will be OK as it goes over SSL, but the password has to be strong. – Andrew Smith Jul 14 '12 at 01:20
  • 3
    Well, i could put some logic in my server that bans a client that attempts too many passwords. Would that prevent DoS and password guessing? – Steven Lu Jul 14 '12 at 01:28

10 Answers10

370

There are a few issues with HTTP Basic Auth:

  • The password is sent over the wire in base64 encoding (which can be easily converted to plaintext).
  • The password is sent repeatedly, for each request. (Larger attack window)
  • The password is cached by the webbrowser, at a minimum for the length of the window / process. (Can be silently reused by any other request to the server, e.g. CSRF).
  • The password may be stored permanently in the browser, if the user requests. (Same as previous point, in addition might be stolen by another user on a shared machine).

Of those, using SSL only solves the first. And even with that, SSL only protects until the webserver - any internal routing, server logging, etc, will see the plaintext password.

So, as with anything it's important to look at the whole picture.

Does HTTPS protect the password in transit? Yes.

Is that enough? Usually, no. (I want to say, always no - but it really depends on what your site is and how secure it needs to be.)

techraf
  • 9,149
  • 11
  • 44
  • 62
AviD
  • 72,708
  • 22
  • 137
  • 218
  • 8
    actually, even with HTTP Digest, you may be able to a hash of the password (`md5(username:realm:password)`, sometimes called HA1). – Bruno May 18 '11 at 20:58
  • 75
    @AviD♦ Imho your points 3) and 4) are rarely valid for REST APIs. – Eugene Jun 22 '12 at 19:55
  • In case of basic auth, the password "has to be" stored in the browser, which can only be done via a cookie, which can never be considered safe. I posted a similar question here: http://stackoverflow.com/questions/27177224/how-to-keep-state-at-the-client-safely/27177995#27177995 My conclusion was that Basic Auth is NOT safe, that it should NOT be used as such, and that storing sensitive data at the client (such as a user password) should not even be considered. – Trace Nov 28 '14 at 02:59
  • 40
    @KimGysen for Basic Auth, the password is NOT transmitted or stored in a cookie, it is sent in the `Authorization:` request header, and stored in a special (protected) part of the browser's memory. Not that I disagree with you, in the general case Basic Auth should not be used, however there are certain situations where the tradeoff might be viable. – AviD Nov 28 '14 at 08:38
  • 2
    The second point is not an issue. Sending credentials with every request keeps your backend stateless. – artkoenig Nov 30 '14 at 18:28
  • 10
    In addition to the "larger attack window," there's no built-in mechanism like account lock out to protect against brute forcing. – Alex Kuhl Mar 06 '15 at 16:08
  • 10
    @Artjom: Sending Basic credentials on every request is an issue, not because you have to keep sending the credentials, but rather because the same string is sent on every request. There are other authentication mechanisms, like HMAC, where the Authorization header cannot be decrypted back to the user's secret, and the server can authenticate the request without actually knowing the user's secret. In this mechanism, the string sent on the Authorization header changes based on the hash of the request. – Lie Ryan Aug 06 '15 at 14:28
  • 2
    @LieRyan I honestly don't get it :-\. What's the problem with sending the same string? Is it because variety is the spice of life? – DavidS Mar 11 '16 at 22:00
  • 5
    @DavidS: replay attack. Also, if you pass your traffic through a proxy or CDN service, you have some assurance that an attacker cannot attack the proxy/CDN to alter the user's requests. – Lie Ryan Mar 11 '16 at 23:37
  • 1
    @Bruno, HTTP Digest is *worse* because it requires the server to store the user passwords in plain text! – Jacco Mar 28 '18 at 11:56
  • @Jacco In principle, the server could only store `md5(username:realm:password)` and not need the password in clear (you can check the content of a file generated with `htdigest` for example). This is implementation dependent. That said, it's still not great (also with the downside of being easily vulnerable to downgrade attacks to Basic). – Bruno Mar 28 '18 at 12:55
  • 2
    "Larger attach window" So normal session token that sends as cookie also have the similar problem right? – Jithin Jose Oct 05 '18 at 08:51
  • 4
    @JithinJose that wouldn't include the user's password, nor is it static + valid for a very long time. – AviD Oct 05 '18 at 09:47
  • @LieRyan HMAC isn’t one of the standard HTTP authentication mechanism, unlike Basic and Digest. Were you talking about [the one implemented by AWS](https://docs.aws.amazon.com/en_us/AmazonS3/latest/dev/RESTAuthentication.html#ConstructingTheAuthenticationHeader)? – Franklin Yu May 02 '19 at 03:55
  • 1
    @LieRyan: Both replay and the proxy/CDN scenario are not possible with TLS, unless TLS has a flaw. – President James K. Polk Mar 30 '20 at 14:35
  • TLS 1.3 adds PFS which should reduce the attack windows and eliminate that first point. Point 3: browsers / apps / whatever does the request may also as well cache the body. In general if someone has control over the client it doesn't really matter what authentication method is used (cookie accesss, memory access). Point 4 is also valid for any kind of form data. I don't think shi**y behaviour of the browser (unencrypted storage of sensitive data) is something that basic auth should be blamed for. In general I agree: if you can choose, you should use more advanced auth. methods. – omni Mar 13 '21 at 16:38
  • @JithinJose as a best practise for exactly that reason you should add a random nonce to every request you make. This will make it much harder to decrypt the transmitted data if someone tries to. – omni Mar 13 '21 at 16:43
  • @artkoenig just because you enjoy one of the consequences it doesn't mean it's not an issue. Other methods exist to keep your backend stateless without spoiling sensitive user data all over the place but sure: they are harder to implement. – omni Mar 13 '21 at 16:47
  • Most sites use cookies/tokens for auth, which is sent in headers. – noɥʇʎԀʎzɐɹƆ Apr 12 '21 at 20:33
  • 1
    @noɥʇʎԀʎzɐɹƆ okay? This question from ten years ago was about HTTP Basic Authentication (via the Authorization header), not about cookies or tokens? – AviD Apr 13 '21 at 10:43
  • 1
    @AviD Most of the alternatives to HTTP Basic have the same flaws you mentioned. And SO is a wiki, so info from 10 years ago should stay accuraye. – noɥʇʎԀʎzɐɹƆ Apr 14 '21 at 00:12
  • @noɥʇʎԀʎzɐɹƆ okay, but none of the flaws I mentioned actually apply to cookies or tokens (assume you mean something like JWT?) - IF done right. And I could split hairs and point out that the OP was asking if THIS is secure, not if alternatives are :-) – AviD Apr 14 '21 at 08:20
  • @AviD I don't mean JWT. I mean the very, very common pattern of passing an `Authorization: Bearer` token, like Discord does. – noɥʇʎԀʎzɐɹƆ Apr 15 '21 at 14:33
  • 1
    @noɥʇʎԀʎzɐɹƆ okay, but none of the issues mentioned apply here either? Like, no password is stored, cached, or passed, right? And even the bearer token isn't permanently cached by the browser. So what point am I missing? – AviD Apr 20 '21 at 08:37
  • "There are a few issues"? It feels like you are implying Basic Auth is inherently less secure than an alternative, but without TLS you're compromised either way. And whatever additional protections the browser might provide for alternative methods, could also be implemented for Basic Auth. – Yeti Jul 31 '22 at 12:58
  • 1
    @Yeti Hmm, did you read past the first line? I am not implying, I am saying it explicitly - in certain situations, with specific circumstances, yes it is less secure, irrelevant of TLS (it is specifically mentioned, back then it was more commonly known as SSL ¯\_(ツ)_/¯) . The browser's additional protections, to some extent, do not apply to Basic Auth. As noted in the answer. – AviD Aug 01 '22 at 23:13
  • @noɥʇʎԀʎzɐɹƆ sure but Discord sessions are just that: sessions. You only transmit your password over the wire once per session (or for reauthenticating for some actions) and you can't use (when implemented properly) an expired session later – Justine Krejcha Aug 24 '22 at 10:11
  • 1
    The person I was responding to was. Bearer tokens (which Discord and many other services use) are ostensibly revokable in some fashion, for example by logging out, whereas the issue with Basic auth is that you're transmitting your username/password for every single request – Justine Krejcha Aug 27 '22 at 09:52
  • 1
    @JustineKrejcha Ahh you're absolutely right, I apologize for that - reading it now in context, your comment absolutely makes very good sense :-) Thanks! – AviD Aug 27 '22 at 21:09
  • Of course, no worries :) – Justine Krejcha Sep 01 '22 at 09:35
112

Try to think of it this way: When you are logging in to any website using SSL, you are most likely passing password in plain-text over HTTPS (for eg GMail).

The only difference that Basic-Auth makes is that username/password is passed in the request headers instead of the request body (GET/POST).

As such, using basic-auth+https is no less or more secure than a form based authentication over HTTPS.

Nemo
  • 1,607
  • 1
  • 14
  • 11
  • 56
    There is one slight difference between those situations: with http basic authentication the password is sent for *every request*, while with a form based login it is sent only once and then something like a session cookie is used. This *very slightly* decreases the attack surface. – Pepijn Schmitz Nov 04 '15 at 10:51
  • 3
    The user password are sent only once but the auth cookie is sent on every request too, so the question is only to send the user and password instead cookie auth – deFreitas Feb 08 '16 at 12:46
  • 2
    @deFreitas and thus you have the premise of OAuth: using another token for auth instead of sending the u/p all the time. – cottsak Mar 02 '16 at 05:27
  • 22
    I think there is more than a slight difference: in the form POST example, the initial page rendering has to be sent over HTTPS before the user decides to enter their credentials and POST them back (securely). With HTTP basic auth, even if the server refuses to service a non-HTTPS request and redirect to HTTPS, the credentials have already gone over the wire insecurely and are then venerable to MiTM snooping. The client has to decide to POST HTTPS initially or risk an insecure channel. This is less likely with the form POST scenario. – cottsak Mar 02 '16 at 05:30
  • 6
    @PepijnSchmitz I would note the difference of a session key (which can be invalidated) is hugely different than having login credentials stolen. Damage can still be dealt while another party has your private session key, but it's much more limited in nature, especially since you can have your application log out from the API after it's finished executing to invalidate the key. – Jeremy Kato Aug 05 '16 at 18:12
  • @cottsak: That is incorrect. If the server refuses HTTPS then no connection is made at all. – President James K. Polk Oct 01 '20 at 00:06
  • @cottsak 'the initial page rendering has to be sent over HTTPS' - What if you're on a public wifi and someone is hosting a fake http://gmail.com site (http not https), and it's the first time the user has gone there on this particular device (so HSTS doesn't help)? In this case the credentials would also go over the wire insecurely. – David Klempfner May 29 '22 at 06:35
  • @DavidKlempfner almost all browsers will warn users when a page loads of HTTP (not S) so that is a warning the user should see. – cottsak May 30 '22 at 06:49
26

Basic Auth over HTTPS is good, but it's not completely safe. Similar to how Fiddler works for SSL debugging, a corporate HTTPS proxy is managing the connection between the web browser and the Proxy (whose IP address appears in your webserver logs). In that case the HTTPS password is decrypted, and later re-encrypted at the corporate proxy.

Depending on who is managing the proxy, and how its logs are used, this may be acceptable or a bad thing from your perspective.

For more information on how SSL interception is done, see this link:

When the SSL Proxy intercepts an SSL connection, it presents an emulated server certificate to the client browser. The client browser issues a security pop-up to the end-user because the browser does not trust the issuer used by the ProxySG. This pop-up does not occur if the issuer certificate used by SSL Proxy is imported as a trusted root in the client browser's certificate store.

The ProxySG makes all configured certificates available for download via its management console. You can ask end users to download the issuer certificate through Internet Explorer or Firefox and install it as a trusted CA in their browser of choice. This eliminates the certificate popup for emulated certificates...

Some companies get around the certificate pop-up issue mentioned above by deploying the root certificates (of the Proxy) to each workstation via GPO. Although this will only affect software that uses the Microsoft Certificate store. Software such as Firefox needs to be updated differently.

makerofthings7
  • 50,488
  • 54
  • 253
  • 542
  • 1
    Actually this depends on what site you're talking about. E.g. if youre browsing to your bank from work, and they use Basic Auth, that's not getting decrypted by the proxy at your work. SSL goes right through that. – AviD Dec 06 '10 at 06:16
  • 1
    This makes no sense to me - what scenario are you thinking of? Proxies can't see what is inside an https session, if the browser set it up with the actual endpoint, properly authenticated with a a good cert (or DNSSEC or whatever). – nealmcb Dec 06 '10 at 06:23
  • 3
    The negative voter should read the linked documentation, since this is a real and valid point that isn't broadly known. Docs: http://www.bluecoat.co.jp/downloads/manuals/SGOS_DG_4.2.x.pdf – makerofthings7 Dec 07 '10 at 03:40
  • 5
    Yeah, you're right - BlueCoat does look like corporate malware, using FUD to make business insecure. – AviD Dec 07 '10 at 09:00
  • 2
    And btw - Chrome does use the Windows Certificate Store... – AviD Dec 07 '10 at 09:01
  • Some kind soul should upvote this answer so it's no longer (-1) This answer contains true, factual information – makerofthings7 Feb 07 '11 at 22:07
  • 3
    @AViD, there are some cases where corporate proxies actually _do_ decrypt the SSL traffic, by presenting their own certificate (which is signed by an internal corporate cert that is imported as a trusted root authority cert on all corporate workstations). My company does this for a few sites including Gmail (but not for banking sites). It works, and is often invisible to users because the company also manages the desktops/browsers. Note that Strict Transport Security (HSTS) can defeat this ... it was the firefox HSTS warning that alerted me to it in the first place! – Michael Lucas Dec 17 '15 at 17:28
  • @MichaelLucas - yes, see the previous comments regarding BlueCoat (a popular malware, erm, software vendor in this space). As I implied, this is an anti-pattern, with numerous downsides (e.g. the user has no indication on invalid or problematic server certs... and that's besides the privacy issues) – AviD Dec 17 '15 at 20:53
  • @MichaelLucas To my knowledge if they do this properly HSTS cannot defeat this, can you elaborate on how HSTS addresses this? I think you would notice if if you actually take a look at the Certficate Chain in your browser, and begin to wonder why your company is the CA of a third-party site. If my company would do this however, I would complain! – Nappy Feb 15 '16 at 20:44
  • 1
    @Nappy Possibly what was meant was [HPKP](https://en.wikipedia.org/wiki/HTTP_Public_Key_Pinning) rather than HSTS? That could certainly defeat the nasty corporate scanners. Except that Wikipedia states that most browsers disable HPKP checks for certificates with private roots specifically to allow such scanners. Oh well... – Søren Boisen Jul 01 '17 at 21:23
  • 1
    If the company does MITM attacks on employees traffic it defeats almost any form of authentication, not just Basic Auth. So unless the web server is willing to use something more complex like 2-factor auth, Basic is almost as secure as any other form of authentication. – Poma Jan 11 '19 at 12:30
13

You note the need for authenticating the client and ask about the security of HTTP basic auth, over SSL. This is what SSL was designed for and will work fine so long as the password is a good one. If you're really setting this up for just a single client, that is easy to ensure by picking a long random password, e.g. 12 characters using a good source of randomness, or other techniques discussed at this site.

Your client also does need to ensure that you have the right cert for the server. In the situation like what you describe, using a self-signed cert as described at the python ssl page referenced will be fine.

Benoit Esnard
  • 13,979
  • 7
  • 65
  • 65
nealmcb
  • 20,693
  • 6
  • 71
  • 117
  • 2
    If you are going self signed, be sure to communicate what the SHA1 and MD5 fingerprints of the certificate should be so they can verify its legitimacy upon connection. Or distribute ahead of time, if feasible. – chao-mu Jul 14 '12 at 03:27
  • 2
    There is another concern with using HTTP basic authentication: the full password is sent over the SSL tunnel. In other words, the password is not hashed before being submitted, and could thus possibly be captured (bug in your application code, etc). This is usually not a major concern (this is true for most passwords you submit over HTTPS, even in website login forms, and even in password SSH), but is worth taking note of. – Chris Kuehl Jul 14 '12 at 04:43
  • @ChrisKuehl Aren't there strong arguments against doing any crypto in client-side javascript? Is that what you are suggesting? Seems to me like TLS is about as good as I can get other than paying for signing the certificate. – Steven Lu Jul 14 '12 at 09:23
  • @StevenLu not that I'm aware of or that I can find quickly, but I'd be interested in reading anything about the topic. I can't see any way that hashing something preliminarily before sending it serverside could decrease security, even if serverside further hashes it before storing it. I would be tempted to use [SSL/TLS auth](http://goo.gl/xmzFI) instead (modern browsers allow 2-way auth with websites using key auth), especially for a page that is not meant to be viewed by regular users. This depends a lot on your use case, though, and is probably difficult with your Python webserver. – Chris Kuehl Jul 14 '12 at 17:08
  • What about TLS in TLS, I think 4 times wrapping it would be more secure than wrapping it once. This way you can spread the root keys into different locations, so if you use 4 companies to do it, it's likely that they (THEY) won't have the secret root key, or all of them. – Andrew Smith Jul 14 '12 at 17:59
  • Take a look: http://www.matasano.com/articles/javascript-cryptography/ – Steven Lu Jul 14 '12 at 19:37
  • 1
    @StevenLu interesting, but missing the point; TLS auth, [as implemented in browsers](http://www.browserauth.net/tls-client-authentication), doesn't involve JavaScript. It's a feature of the browser itself. There are issues that make it not suitable for use with user-facing authentication, but for developers/admins, I think there's a strong case that can be made for it. – Chris Kuehl Jul 14 '12 at 23:00
  • @ChrisKuehl So, I guess I will need to dig a little deeper to find a way to set up my server to do a full TLS client authentication? – Steven Lu Jul 14 '12 at 23:55
  • @StevenLu, your setup sounds fine to me, but it all depends on how much security you want. Just throwing out an additional idea :-). – Chris Kuehl Jul 15 '12 at 00:25
  • @ChrisKuehl TLS server auth is definitely sufficient for my needs and I was pleasantly surprised to discover the simplicity with which I was able to set it up. I now wonder what it would take to get full client auth, though. – Steven Lu Jul 15 '12 at 00:30
10

Depends entirely on how secure it needs to be. Basic auth over ssl will still be sending credentials in plain text, which means you only have one layer of protection.

You would be better off to hash the password with a nonce, or better yet use claims model that passes the auth over to a trusted 3rd party.

Steve
  • 15,215
  • 3
  • 38
  • 66
6

I am using this myself for many things, and as long as you don't ignore any TLS warnings from the browser you should be good.

TLS works below HTTP, so any data transmitted through HTTP will be encrypted. It'll be as secure as submitting any password form.

Instead of using a self-signed certificate though, I would suggest using Let's Encrypt. They provide free certificates and are trusted by Microsoft, Mozilla, etc., and thus it won't give a TLS warning in the browser. I think it's better to use this instead of a self-signed certificate; if you ever see a TLS error you know it's real and not just because your cert is self-signed.

Luc
  • 32,378
  • 8
  • 75
  • 137
  • I'd definitely do something like this especially if it's free. The "invalid certificate" errors are pretty glaring. – Steven Lu Jul 15 '12 at 01:08
  • Yes, StartSSL is really a sorta homebrew solution, but it's trusted by big parties so I guess it's fine as long as you don't secure anything worth millions with it. Anything is better than a self-signed certificate. The way to make self-signed secure is to check the fingerprint, but you can still do this while using (for example) StartSSL. – Luc Jul 15 '12 at 17:59
  • I am hosting my secure content on a different server from one which I can set the target domain for a certificate (to be issued by StartSSL). This is because I am not paying for a VPS with a static IP, I am using the No-IP service to give me a redirect to my IP. Is it possible for me to obtain a key/certificate that will allow me to open my site from anywhere without it showing invalid cert errors? – Steven Lu Jul 17 '12 at 03:54
  • So it seems to be clear to me that with a dynamic IP there is absolutely no way to set up a proper SSL certificate. Okay I guess I am stuck with the browser error then (unless I do some kind of proxy setup). – Steven Lu Jul 17 '12 at 04:02
  • Update: StartSSL have closed their doors. Your next best option is Let'sEncrypt. – starbeamrainbowlabs Dec 16 '17 at 18:22
  • 1
    @starbeamrainbowlabs Thanks! I updated the answer. – Luc Dec 17 '17 at 12:35
4

Plenty of large and popular sites use basic (or another forms-based) auth over HTTPS. It usually gets a 'sigh' from security-conscious people. Can you hash the password on the client-side and send the hash instead? That would raise the bar a bit more.

That said, it's generally considered acceptable, under the condition that your landing page hosting the logon form is HTTP/S as well. In your case of a RESTful API you probably don't have a landing page so that's okay. If you can, verify your application with some free security tools like Watcher and Skipfish.

Weber
  • 1,016
  • 1
  • 6
  • 10
  • 6
    only a challenge-response with hash is an upgrade in security, otherwise the attacker can just snoop the hash and still get access when the session expires – Hubert Kario Jul 19 '11 at 22:14
3

Another argument not mentioned (I guess) so far is the fact that many mobile devices such as smart phones do not let the user check the certificate when doing basic auth over HTTPS in the browser. That means that unlike with forms based auth you cannot bypass the basic auth popup which is a modal dialog on most mobile platforms to check the certificate before you enter your credentials. This might pose a risk when an attacker uses a valid certificate.

lightxx
  • 131
  • 3
2

Here is a bit more context for history. Just like others said Basic Auth over TLS works well if you can live with a few limitations.

Used on the client side, you probably need to deal with session management, which is rather hard with Basic Auth.

On the backend, Basic Auth performs well but relies entirely on TLS for confidentiality and integrity. It is similar to token based auth. If you need anything more sound, consider using a signature schemes or TLS Client Auth.

Daniel Szpisjak
  • 1,895
  • 11
  • 19
1

Quoting the spec https://datatracker.ietf.org/doc/html/rfc7617#section-4

Because Basic authentication involves the cleartext transmission of passwords, it SHOULD NOT be used (without enhancements such as HTTPS RFC2818) to protect sensitive or valuable information.

MDN makes a similar comment https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#security_of_basic_authentication

As the user ID and password are passed over the network as clear text ... the basic authentication scheme is not secure. HTTPS/TLS should be used with basic authentication.

Colonel Panic
  • 2,134
  • 2
  • 22
  • 24