Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Detect Caps Lock with JavaScript (davidwalsh.name)
65 points by fagnerbrack on March 12, 2024 | hide | past | favorite | 68 comments


A good way to reduce your support burden is to try user passwords twice: once how they entered it and the second with case reversed.


I have been online since 1992 and have never seen this pattern.


Facebook removes two bits of entropy on login: it tries the entire passphrase with case reversed and just the first letter with case reversed. There's also some fanciness with username correction if you have old cookies.


Doesn't this only detect when you press caps lock and turn it on? That's the result I got from testing it out in the browser console.

Despite not using the site anymore, I appreciate how facebook handles this. If your password is incorrect, it checks again with the case swapped to account for caps lock being on.


> Doesn't this only detect when you press caps lock and turn it on? That's the result I got from testing it out in the browser console.

No, if CapsLock was set to on when you pressed the key, getModifierState('CapsLock') returns true. It is true that this doesn't let you query the caps lock status directly at will, instead you have to wait for a keyboard event. But it is not merely telling you that Caps Lock itself was pressed, rather that a key was pressed while CapsLock was enabled.

This is exactly how it's working for me as I test it on this textarea.

So if you wanted to add one of those "Hey, Caps Lock is on" warnings to a password field, you could do so, you'd just have to wait for the first key to be pressed.


> If your password is incorrect, it checks again with the case swapped to account for caps lock being on.

I love this idea, going to add this to future projects.


Don't forget about internationalization. Not all language have uppercase and lowercase characters [0], and tbh I'm not sure what effect (if any) caps lock has for these. And rules for converting case can sometimes be tricky.

0: https://en.wikipedia.org/wiki/Letter_case#Bicameral_script


But it’s not core functionality, it’s just a convenience.

Making it more convenient for everybody equally is an admirable goal, but should a trivial change that makes life a bit easier for many people be scrapped just because making it easier for everyone else is difficult? Specifically here where the experience doesn’t significantly regress for anyone.


I never said it should be scrapped... just that it needs to be considered and tested.


This is a terrible idea!

It means that the passwords have far less entropy.

It means the uppercase you password when generating a hash. Good lord.


> It means the uppercase you password when generating a hash. Good lord.

No it doesn't. Say your password is "Abc1". When you sign up, they would hash "Abc1". Then when you login, say you type "aBC1". The site would first hash "aBC1" and find that it is incorrect. Then it would invert the case to "Abc1" and try again, and it would work. It's basically just automating a second attempt. In fact, I wonder if it even counts as a second failed attempt if both failed.

If someone were able to make brute force attempts on the website, it would still end up evaluating the passwords the same number of times as if the inverted case wasn't checked (the attacker would just need to invert it themselves) and in fact would likely slow down the attack because they are forced into checking inverterted case passwords. But that's moot anyway because the website limits login attempts. And if the database leaked, it's not stored any differently than if they didn't invert the case.

Of course I'm making assumptions about the implementation (I didn't know they did this until this comment) and it could be done poorly but I would hope a company as big as meta/Facebook put at least this amount of thought into it.


Ok, but I thought the implication was that it didn’t do retries but just uppercased passwords.

This makes more sense, and obviously a better idea.


Whoa, let's not all freak out here (for this post and sibling posts). While I don't think I would personally do this, it only removes 1 bit of entropy because the case is swapped, and it only does that when checking the password. This does not imply they uppercase/lowercase the password prior to hashing at all, nor that foobar123 will work when the hashed password is FooBar123. Rather that fOObAR123 can be transformed by swapping case to FooBar123 and then checked against the hash.

Don't forget that the shift key makes things lowercase when Caps Lock is turned on.


It doesn't remove even a single bit of entropy.

For an offline attack, where you have to attack Facebook's bespoke "password onion"[1], you would still have to compute both hashes. There is approximately zero impact on cracking strategy.

There may be an argument to be made that Facebook would have otherwise used a larger work factor had they not had to do double the work for wrong passwords, but the common case is the password being correct, so I doubt this was a significant consideration in the parameter selection.

Even for the online case, I really don't think it affects security in a nontrivial way.

1. https://bristolcrypto.blogspot.com/2015/01/password-hashing-...


I agree, for offline attacks there is no impact. Very interesting article. What is up with $\$$cur there btw? In PHP that would be a gnarly indirection-- even if it's something in FB's codebase, why keep it on the slide like that?


Technically, one bit less, which is insignificant for strong passwords.

And for weak passwords... Well, it's not like that one extra bit would have made a difference.


No...they literally have the password you just entered. In plain text. They can change the case of that and compare against the DB hash twice. The entropy for someone trying to brute force the hashes directly is identical.


No, you don't ignore the case, you swap it and try again. This could be implemented as a browser extension:

- User types pA$$WORD1 and clicks Sign In

- Frontend sends that to the server

- Server responds "incorrect"

- Frontend tries again with Pa$$word1

- Server responds "correct" and user is logged in


So now every wrong password is using 2 attempts?

You either have to double the number of failed attempts before a lockout or deal with users getting locked out much quicker.

Thus causing more frustration than if you'd done nothing at all to address the capslock issue (that they're going to have to notice and fix anyway at some point, when they inevitably need to type again)


Well, in Facebook's case, it's more than double (it appears to be 3 or 4 at most), and it is done smartly (the reverse caps try is only performed if you typed in your password with capslock turned on), and with a proper system to throttle attempts before locking an account, it seems reasonable to me. See https://security.stackexchange.com/a/214815 and its sources.


A user can only have one password. How does entropy come into play ?


Entropy here is referring to how random the user's password is, and thus how difficult it will be to guess it. For example, a four character password which can be comprised only of lowercase a-z has much lower entropy than a four character password which can have A-Z and a-z (and the case is significant).

Obligatory XKCD: https://xkcd.com/936/


I may be misunderstanding it. But they are switching the case, not turning it lowercase. So trying both AbCd and aBcD, because that's what you'd type if caps lock was on.


Just came here to say, please don't do this to your users, or your business.

Also, can someone please tell me that Facebook doesn't really do this?


Facebook does do this, and it's perfectly fine: https://security.stackexchange.com/a/214815

It exchanges a few bits of entropy for a much smoother user experience, and it doesn't actually aid an attacker much (they could just try the permutations themselves)


Thanks for the link. That's helpful info.


yOUaREwRONG1!


You could detect caps lock by looking for these conditions:

* consecutive uppercase alpha characters are entered

* the shift property on the keyboard event is false


> consecutive uppercase alpha characters are entered

Why consecutive? Only one uppercase character without the shift key being used should be sufficient.

That being said, it's probably not the best method as the users can also copy/paste passwords, or use a password manager.


That is why consecutive key events is necessary, to distinguish character versus a string paste operation.


Isn't keypress and paste two different events?


> Ideally developers could let the user know their caps lock key is activated.

That would be up to the User Agent (the browser), not the website.


I dream of a parallel universe where browsers took the lead in crafting innovative UI’s for standard web forms, with things like password prompts behaving intelligently, dropdowns supporting advanced autocomplete, excellent date pickers, caps lock reminders on password dialogs, etc etc.

Websites could have been simple to make with basic markup, leaving UX niceties to the browser vendors.

The world we live in is about as far from that as you get, with the stock UI for <input> elements being about par for 1992 UI toolkits, if even that.


The mobile platforms were a chance to reboot that part, and have browser do a lot more UI wise with custom handling of the different data types (dates, passwords, phone numbers, ranges etc.)

It just didn't pan out to tablets and desktop computers. But it might not be too late ?


> It just didn't pan out to tablets and desktop computers. But it might not be too late ?

Safari has a caps lock indicator on password fields on every platform, and has had it for several years - at least since Safari 12 on macOS 10.12 (circa 2018), possibly longer, but I don't have an older VM to test on.

Gecko has an open feature request for this, from 2 years ago: https://bugzilla.mozilla.org/show_bug.cgi?id=1757348

Chromium has an open feature request for this, from 3.5 years ago: https://issues.chromium.org/issues/40722752


In particular, the input select multiple is atrocious with default styling.


Well, they're not, which means web developers are picking up the slack.


Stay your lane, and if you really feel the itch go contribute to firefox or something


If you think I'm a front-end developer, you are mistaken. I just empathize with them.



Ah, so you were merely replying at me, rather than to me.


This is a public forum, we're not DMing


How would the browser know when/how to display the capslock status? It doesn't know what any given web site is doing wrt to keyboard input. Firefox adds a capslock indicator on the text cursor but not all pages use standard input fields. They might use custom UI elements, or no visual elements at all. Some sites may not even care about capslock (e.g. an arcade game).


`<input type='password'`, just like TFA was talking about?


> That would be up to the User Agent (the browser), not the website.

Relevant: Safari has done this for ages.


It'd be nice to be able to do this without a keyboard event so that you should show an indicator in the password field that caps lock was on before they started typing.


You should be able to do this just fine with MouseEvents, and use `mouseup` or `mousedown` on the input box to trigger your "Caps On" icon, visible before the user starts typing.

docs: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/...


It wouldn't even need to be an event on the input, it could be any key or mouse event on the document, including mousemove.

That being said, I think it would be better if browsers would implement this; that would make it more efficient and more predictable.


> mousemove

True, but I was trying to avoid handlers being fired constantly. Just something to consider.


> so that you should show an indicator in the password field

So I take it none of the OS/browser vendors besides Apple are doing this natively yet?


It could be an onFocus as well, I presume.


David Walsh! Blast from the past. I used to read his stuff when I was starting out almost 20 years ago.


I dunno. Does the password use case really justify writing and maintaining this code rather than just relying on the little LED light on just about every keyboard that does the same thing? The tiny amount of user pain doesn’t seem to be worth it. Part of engineering is deciding whether we should, not just whether we can.


There are many keyboards without Caps LED. Even if your keyboard has, do you look at LED on your keyboard on every time typing password?


No but I realize it’s in after a few failed attempts and don’t hold it against the website for my error.


The big pitfall in the api of browser and keyboard is there is not a method to get the status (keys pressed) of the keyboard.

I know that it is about security stuff, but for the games in js is a bad situation when the canvas lost the focus and the keys pressed change.


I fought with this so much today.

Our robots can be driven remotely via a web app. But there’s ways to accidentally get buttons stuck down because keyup is never guaranteed and you can’t get key state. Two cases: holding down forward key and blur the tab, or open contextmenu.

There’s workarounds of course. But it’s comical spending so much time on something so simplistic.


This might be an appropriate use for the Gamepad API which can be queried on every animation frame for a button’s state.

https://developer.mozilla.org/en-US/docs/Web/API/Gamepad_API...


The Gamepad API is fun, but we’re not trying to implement a gamepad.


How is this a security issue?


You can handle the onblur event and use it to clear all pressed keys.


The pair of animated GIFs adverts ("Request Metrics") inserted into the body of the article are simply awful.


Poor formatting aside, this feels like a blogspam tutorial. Feels like a weird article to be this high on HN. I don't see what's notable here in the vanilla JS features that the author is pointing out.


"blogspam tutorial": What a brilliant phrase. My teammate and I were recently joking about the same for Python blogs. If you Google any "simple" Python programming question, the results are overloaded with "blogspam tutorials". I cannot wait until ChatGPT will replace all of that crap.


I remember learning Python for my first time, and being constantly inundated with this junk. That or absolutely decade outdated W3Schools. My fear with ChatGPT is that someone's going to set up a no-effort spam generation machine that will make it harder for beginners.


I was unaware of this `getModifierState` feature. I learned something that may help me in the future.


If you google 'detect caps js' you will find hundreds of articles on this very topic, and bard will provide a correct solution in the top of the window. No need for this to be here.


Third result is a far better StackOverflow post as well, without the irksome formatting of the posted link: https://stackoverflow.com/questions/348792/how-do-you-tell-i...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: