2.5 KiB
Authentication in Golang
Use header
Use the http header or the body, but avoid using cookies to transport tokens etc (because of CSRF)
Implementation
# create password/user
update_password(password):
generate salt
db.store(hash(salt + password))
#login
get_token(userId, password):
if not hash(salt + password) == db.get(salted_hash_of_password): # use timing-attack resistant compare here
return FAILED
generate selector
db.store(selector)
generate salt
generate auth_token
db.store(salt, hash(salt+auth_token))
return selector:auth_token
#authenticate
validate_token(selector, auth_token):
if not hash(salt+auth_token) == db.get(salt, salted_hash_of_auth_token WHERE selector): # use timing-attack resistant compare here
return UNKNOWN_TOKEN
return AUTHENTICATED
idea: replace selector with userId?
JWT
{
"userId": "id",
"userRole": "role",
"expiryTime": "now+10min"
}
We use JWT with a lifespan of 10min and an in-memory db to blacklist revoked tokens. So if for e.g. a user changes it's password, we would add the userId and the time of the change to the blacklist, filtering out all tokens that have been issued before.
After a server restart, all tokens will become invalid as well, since we can not be sure which ones were 'on the blacklist'. This could be mitigated by making the blacklist persistent during restarts.
If a token has expired (either by a server restart or after 10min), a new token is requested with a 'long lived' refresh-token (lifetime of ~1 week) that is stored in a database.
Pros:
- less DB lookups in general
Cons:
- timestamps of blacklisting could become a problem (maybe add 1 second or use timestamp returned by n-th node when it has received the update).
- increased load on db + service since we need to issue new jwt for everybody.
SSL/TLS
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout keyFile.key -out certFile.crt
CRIME/BREACH http compression attack
While we do not use a CSRF token, headers sent to the /api
still contain
private data.
If you are using http/1.1 or lower and have compression enabled on your proxy, you would be .
CRSF
We check for a http header like this X-YOURSITE-CSRF-PROTECTION=1
. This should
be enough, according to
cheatsheetseries.owasp.org
XSS
We rely on Vue.js's ability to escape user-input in templates.