Pino bio photo

Pino

I (infrequently) blog about data science, business intelligence, big data, web technologies and free software.

Twitter LinkedIn

I had a beautiful time today trying to figure out why JWT authentication was not working in my server. Surprisingly I found little information about it in the Internet.

I was using Flask locally and the application worked wonderfully. However, when I tried to test the application in a server, I got the following error:

{
  "description": "Request does not contain an access token",
  "error": "Authorization Required",
  "status_code": 401
}

The error message in the server was clear: the access token was not present in the request.

ERROR:flask_jwt:Authorization Required. Request does not contain an access token

How was it possible? My script to test the API endpoints was sending the Authorization header correctly:

def get_access_token(host):
    url = host + '/auth'
    data = '{"username":"usernameexample","password":"passwordexample"}'
    headers = {'Content-type': 'application/json'}
    resp = requests.post(url=url, data=data, headers=headers)
    resp_json = resp.json()
    access_token = resp_json['access_token']
    return access_token

def test_protected_access(host, access_token):
    headers = {
        'Authorization': 'JWT {}'.format(access_token),
    }
    resp = requests.get(host + '/protected', headers=headers)

access_token = get_access_token(host)
test_protected_access(host, access_token)

And the headers were being received in the local server:

Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6MSwiaWF0IjoxNDkxMjE1MDk0LCJleHAiOjE0OTEyMTUzOTQsIm5iZiI6MTQ5MTIxNTA5NH0.F4pbN71cJd1JPj2oO6O-YoatcF6_1My7yRsUhokvwCE
Host: localhost:5000
Content-Length:
User-Agent: python-requests/2.13.0
Accept: */*
Connection: keep-alive
Accept-Encoding: gzip, deflate
Content-Type:


dude where are my headers (dude where's my car meme)


Unluckily, this time finding the problem was not as easy as googling the error that I received either on the server or on the client side. After reading some documentation I found out that the authorisation header is not passed through to WSGI applications by default for security reasons. But the fix is very simple, you just have to use the WSGIPassAuthorization directive:

WSGIPassAuthorization on

This is an example of apache configuration file using this directive:

<VirtualHost *:80>
		ServerName example.com
		ServerAdmin hithere@example.com
		WSGIScriptAlias / /var/www/example/example.wsgi
		WSGIPassAuthorization on
		<Directory /var/www/example/example/>
			Order allow,deny
			Allow from all
		</Directory>
		ErrorLog ${APACHE_LOG_DIR}/error.log
		LogLevel warn
		CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

I hope this helps anyone googling these errors or at least helps me not forget about this next time :)