YetAnotherToDoList/server/auth/README.md

92 lines
2.5 KiB
Markdown
Raw Normal View History

# 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
```json
{
"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
```bash
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](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#custom-request-headers)
## XSS
We rely on Vue.js's ability to escape user-input in templates.