printf vs printlnBecause of some kind of buffer flushing stuff printf doesn't work well in threads. [[https://stackoverflow.com/a/61538163][Answer
on [clojure] printf in sub-thread outputs nothing]].
The body of a request in this setup is an input stream that needs to be consumed.
The proper way seems to be using so called "middlewares" but I just wanted to at least see it. It took a decent amount of searching probably because nobody does this.
I am using email address as a user ID. Normally, a user should be able to sign in with email+password but server side, we should generate an ID.
For signin, we would get the email, lookup the user by email, and get their ID. Using the email directly as a key makes it more complicated if the user wants to change their email.
Normally, websites don't distinguish between
because this leaks info about who has an account on that site.
The time it takes to serve a request can also give information to an attacker if it takes longer to serve an authentication attempt for a user that exists than for a user that doesn't exist.
Obviously don't do that.
This is not a demonstration of the proper way to do things. It is a demonstration of how the mechanics work.
I am using a library that implements bcrypt.
A first idea for storing passwords would be to store the hash of a
password. For example, user phil@hello.ca
enters hello as their password, we do a
sha1 of it:
echo "hello" | sha1
f572d396fae9206628714fb2ce00f72e94f2258f
and in our database we store
phil@hello.ca | f572d396fae9206628714fb2ce00f72e94f2258f
When I want to authenticate, I give my password hello and the server hashes that and if the hash
of the password matches the hash stored in the database, then I am
granted access.
This approach is vulnerable to attacks like Rainbow Tables.
To mitigate this, we will generate a random string called a salt:
ah23/4#^%_ and hash the concatenation of
the salt and the password.
echo "ah23/4#^%_hello" | sha1
1d81047222b3e980e51bd94b400923c23fe9a9d0to verify passwords during authentication attempts, we will need the salt too so we store
phil@hello.ca | ah23/4#^%_ | 1d81047222b3e980e51bd94b400923c23fe9a9d0
Now when phil@hello.ca wants to
authenticate, we look him up in the database, take the salt plus the
submitted password, hash that and if the result is 1d81047222b3e980e51bd94b400923c23fe9a9d0, then
we let the user in.
With bcrypt, we only store one string that
contains some info on the algorithm, the salt in plain text, and the
hash of salt+password.
I wanted to have the client address stored with the session tokens even if that may not be useful.
This is stored in the key :remote-addr
of the request map:
(:remote-addr request)However, because I use Nginx to reverse proxy requests to the clojure
server, it was seeing 0:0:0:0:0:0:0:1 as
the :remote-addr.
So the solution was to ask Nginx to add the client address to the headers of the request with
location /auth-from-scratch-server/ {
proxy_pass http://localhost:8989/;
proxy_set_header Host philippe-carphin.ca/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Now in the server, I use
(defn remote-addr [request]
(or (get-in request [:headers "x-forwarded-for"])
(:remote-addr request)))to get the value of the header if it is there.
Since this has no purpose related to security, there is no problem
but care must be taken since there are security concerns. I cannot
assume that the presence of the X-Forwarded-For header means that the request
came from my reverse proxy. Indeed, a client could simply set this
header in their request.
Also note that the Nginx variable has the word "add" because this
variable is the value of the X-Forwarded-For header of the incoming request
with the $remote_addr appended to it.
I could just do something like
proxy_set_header Nginx-Remote-Addr $remote_addr
instead.
Packages that I have come across but don't use
crypto-password librarySet-Cookie (response header)Cookie (request header)Forwarded headerForwarded header$proxy_add_x_forwarded_forX-Forwarded-For headerX-Forwarded-For header security
concerns