# 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.