mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-25 03:06:31 -05:00
docs: explain the choice of sha-512 for auth tokens
Signed-off-by: David Mehren <git@herrmehren.de>
This commit is contained in:
parent
b4a65b47f0
commit
708ae86444
2 changed files with 26 additions and 0 deletions
|
@ -39,3 +39,28 @@ Because we need to have empty constructors in our entity classes for TypeORM to
|
||||||
- Should either return a complete and fully useable instance or return a Pick/Omit type.
|
- Should either return a complete and fully useable instance or return a Pick/Omit type.
|
||||||
- Exceptions to these rules are allowed, if they are mentioned in the method documentation
|
- Exceptions to these rules are allowed, if they are mentioned in the method documentation
|
||||||
|
|
||||||
|
## Auth tokens for the public API
|
||||||
|
The public API uses bearer tokens for authentication.
|
||||||
|
|
||||||
|
When a new token is requested via the private API, the backend generates a 64 bytes-long secret of
|
||||||
|
cryptographically secure data and returns it as a base64url-encoded string, along with an identifier.
|
||||||
|
That string can then be used by clients as a bearer token.
|
||||||
|
|
||||||
|
A SHA-512 hash of the secret is stored in the database. To validate tokens, the backend computes the hash of the provided
|
||||||
|
secret and checks it against the stored hash for the provided identifier.
|
||||||
|
|
||||||
|
### Choosing a hash function
|
||||||
|
Unfortunately, there does not seem to be any explicit documentation about our exact use-case.
|
||||||
|
Most docs describe classic password-saving scenarios and recommend bcrypt, scrypt or argon2.
|
||||||
|
These hashing functions are slow to stop brute-force or dictionary attacks, which would expose the original,
|
||||||
|
user-provided password, that may have been reused across multiple services.
|
||||||
|
|
||||||
|
We have a very different scenario:
|
||||||
|
Our API tokens are 64 bytes of cryptographically strong pseudorandom data.
|
||||||
|
Brute-force or dictionary attacks are therefore virtually impossible, and tokens are not reused across multiple services.
|
||||||
|
We therefore need to only guard against one scenario:
|
||||||
|
An attacker gains read-only access to the database. Saving only hashes in the database prevents the attacker
|
||||||
|
from authenticating themselves as a user. The hash-function does not need to be very slow,
|
||||||
|
as the randomness of the original token prevents inverting the hash. The function actually needs to be reasonably fast,
|
||||||
|
as the hash must be computed on every request to the public API.
|
||||||
|
SHA-512 (or alternatively SHA3) fits this use-case.
|
||||||
|
|
|
@ -65,6 +65,7 @@ export class AuthService {
|
||||||
}
|
}
|
||||||
const secret = bufferToBase64Url(randomBytes(64));
|
const secret = bufferToBase64Url(randomBytes(64));
|
||||||
const keyId = bufferToBase64Url(randomBytes(8));
|
const keyId = bufferToBase64Url(randomBytes(8));
|
||||||
|
// More about the choice of SHA-512 in the dev docs
|
||||||
const accessTokenHash = crypto
|
const accessTokenHash = crypto
|
||||||
.createHash('sha512')
|
.createHash('sha512')
|
||||||
.update(secret)
|
.update(secret)
|
||||||
|
|
Loading…
Reference in a new issue