title: HMAC Authentication using Django - Shared Secret
body: <p>For those who read this later: This was part of a hobby project I was doing and back then I wasn't aware of such a thing called Let's Encrypt! Also, I didn't want to purchase an SSL cert; so I was trying to have SOME security without <code>https</code>. Signing does not replace encryption. If you wanna do what I wanted to do, don't. Get a cert from Let's Encrypt. It's Easier and more secure!</p>
  
  <hr>
  
  <p>I am implementing a web service using Django for a mobile app. I decided to use Hash-MAC to authenticate requests (no Oath, no https) but the challenge is what should I use as the shared secret key?</p>
  
  <p>First I considered using The user's password but it required to store passwords in plain text in server-side database. The other solution that came to my mind was salting and hashing password in the mobile app just the way that Django auth app does in order to compute hashed password on client-side. </p>
  
  <ol>
  <li><p>What does Django use as salt? Are they "secret"? Is there any problem with sending them as plain-text to users? We don't have to keep salts as "secret"s in general, but Django may use something that should be kept secret as salts, I don't know, it is about how Django implemented this.</p></li>
  <li><p>Users have to know their salts to compute a hashed password, so the server should provide them with it. An adversary can ask for all users salts and eventually (s)he can have all the salts (Even if there is a limit to the number of times someone can ask for this in a certain time period). Even though salts are not secret but I guess knowing "all" of them can be dangerous. (or maybe I am overly concerned about security!)</p></li>
  </ol>
  
  <p>Requests format:</p>
  
  <pre><code>HTTP request header:
  x-mac-digest: 1d186b9c0fd5cd393f23623f0d167f7b17ac7d1cd74d8442647991d61e756c19
  
  HTTP request body:
  {
    "username": "mjafar",
    ... rest of request in json
  }
  </code></pre>
  
  <p>Authenticating request (simplified):</p>
  
  <pre><code>hash_digest = request.META['HTTP_X_MAC_DIGEST']
  request_body = request.body.decode('utf-8')
  request_json = json.loads(request_body)
  
  user = UserModel.objects.get(username=request_json['username'])
  sharedKey = getSharedKey(user)  # What should it return?
  
  hash = hmac.new(sharedKey, request_body, hashlib.sha256).hexdigest()
  if hash != hash_digest:
      return HttpResponseBadRequest('MAC authentication failed')
  </code></pre>