sahat / satellizer

Token-based AngularJS Authentication
https://satellizer-sahat.rhcloud.com
MIT License
7.85k stars 1.13k forks source link

Security #35

Closed bslipek closed 10 years ago

bslipek commented 10 years ago

I recently read this stack: http://stackoverflow.com/questions/18605294/is-devises-token-authenticatable-secure

in short they say that auth tokens should:

But currently satellizer use the same token, and doesn't change token for the new one from request. So @sahat what do you think? :)

lynndylanhurley commented 10 years ago

@bslipek - here is a rails app that fulfills all of those requirements. The author of the stackoverflow post that you mentioned has reviewed the gem, and he's even contributed code to the project.

The gem should work with satellizer as long as the token refresh feature is disabled.

sahat commented 10 years ago

Thank you for bring up those potential security issues @bslipek, I will take a look at it in more detail tomorrow and update the server demos accordingly.

sahat commented 10 years ago

Ok after looking at that stackoverflow post and other links on the web: @regedarek @bslipek

changed after every request.

I don't think it's necessary. You could do it on the server and Satellizer wouldn't care but I don't see any advantages to re-issue a token on every request. It already has an expiration date after which it becomes invalid. And if you really want to invalidate token before expiration you could change TOKEN_SECRET to something else, as a side effect it will invalidate all tokens.

of cryptographic strength

JSON web tokens are encrypted via HMAC SHA-256 algorithm.

hashed using BCrypt (not stored in plain-text)

Tokens do not contain any sensitive information so there is no need to encrypt them. You could and I am sure there is a way but it's not necessary. Password which are encrypted via Bcrypt are never sent or at least you should not send it with a token.

securely compared (to protect against timing attacks)

Login with email and passwords uses bcrypt.compare for password comparisson between two password hashes, I would hope it is secure. JWT libraries that I use in this project probably do something similar using crypto libraries.

invalidated after 2 weeks (thus requiring users to login again)

It's already doing thia via the exp claim on JWT payload. And in your middleware (Node.js example) on every request you check to make sure JWT is not expired.

bslipek commented 10 years ago

good for me, any other opinions ? thx @sahat

lynndylanhurley commented 10 years ago

The text from this issue was copied from my project so I suppose I should chime in.

Tokens are effectively passwords that users cannot change. Anything that can be accessed using a user's password can also be accessed using a token. With that in mind, I'll expand on each of the bullet points from above.

Tokens should be changed after every request.

If a user's token is compromised, the user would otherwise have no way of knowing that the attacker has access to the account.

But if the token is changed after each request, the user's session would be invalidated as soon as the compromised token is used. This would force the user to re-authenticate, which would in turn invalidate the attacker's session.

Tokens should be hashed using BCrypt

Passwords are hashed using BCrypt so that if an attacker gains access to the database, they will not be able to read the saved passwords.

If tokens are effectively passwords, they should be given the same degree of protection. The danger here is not that the attacker can read the token (it's just a random string), but that the attacker could gain access to the user's account and pose as the user.

For example, if your bank's database was hacked, the attacker would be able to view your account (transactions, balance, etc.). That would be unfortunate, but the damage is limited to read-only operations. But if the attacker was able to take actions on your behalf (i.e. make transactions), then they would have the ability to drain your account.

Tokens should be securely compared

A timing attack is when attackers reverse-engineer encrypted data (passwords, tokens, etc.) by the time that it takes for the server to check their validity. This attack vector can be eliminated by ensuring that it always takes the same amount of time to verify the token. While this kind of attack is not likely to succeed, it's very easy to defend against. So why not?

Tokens should be of cryptographic strength

Again, tokens are effectively passwords. They should be encrypted using the same measures that are used for passwords.

In short, HMAC is not suitable for password/token encryption because it is easily brute-forced. BCrypt uses a slow hash algorithm which makes brute-force attacks more difficult. Here is a more in-depth analysis of this point.


These are the considerations that went into my own project. Please correct me if any of the above points are mistaken. I think this is an interesting discussion, and I'd love to hear what other security experts have to say.

Foxandxss commented 10 years ago

That SO post doesn't have anything to do with us to be honest (I appreciate your concern tho).

JWT tokens are completely secure, you can't tamper it. The only problem is your SECRET, don't share it and you will be fine.

I am not sure of what an attacker could get from cracking the 3rd part of the token (I am not a cracker expert, not even beginner). The 3rd part is signed but internally it contains the header and payload in base64 and I am not sure if cracking it allows you to create another valid signature with tampered data.

A good JWT library will be prepared for timing attack.

Personally I have written a ruby implementation (to be able to use claims) and well, we have some kind of timing attack defense (https://github.com/chupipandi/jwt-rb/blob/master/lib/jwt/decoder.rb#L84-L93). Again, I am no expert, we borrowed that from the other ruby implementation.

About token rotation, nah, that is overkill. There are use cases? sure, maybe a bank, but normally nah. You could rotate secrets per users so you can share a token with a friend and it will be invalidated as soon as you click on a logout (which would involve a real call to the backend, but nothing too fancy).

The good part of JWT is its flexibility, it has a lot and you can do with it what you want.

TL;DR; Don't worry too much my friend.

sahat commented 10 years ago

I am going to close this issue for now. Most of the points raised here are handled on the server-side layer and server-side examples in this repository are just that - simple examples to get things going with whichever language that you might be using.