Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask werkzeug request.authorization is none but Authorization headers present

Tags:

flask

werkzeug

I am POSTing some JSON data and adding an Authorization header. However, the request object does not have the correct authorization property. HTTP_AUTHORIZATION and headers both show the proper authorization details.

{'authorization': None,
 'cookies': {},
 'environ': {'CONTENT_LENGTH': '81',
             'CONTENT_TYPE': u'application/json',
             'HTTP_AUTHORIZATION': 'testkey:',
             'HTTP_CONTENT_LENGTH': '81',
             'HTTP_CONTENT_TYPE': 'application/json',
             'HTTP_HOST': 'test',
             'PATH_INFO': '/v1/test',
             'QUERY_STRING': '',
             'REQUEST_METHOD': 'POST',
             'SCRIPT_NAME': '',
             'SERVER_NAME': 'test',
             'SERVER_PORT': '80',
             'SERVER_PROTOCOL': 'HTTP/1.1',
             'flask._preserve_context': False,
             'werkzeug.request': <Request 'http://test/v1/test' [POST]>,
             'wsgi.errors': <open file '<stderr>', mode 'w' at 0x10d5471e0>,
             'wsgi.input': <_io.BytesIO object at 0x11074c410>,
             'wsgi.multiprocess': False,
             'wsgi.multithread': False,
             'wsgi.run_once': False,
             'wsgi.url_scheme': 'http',
             'wsgi.version': (1, 0)},
 'headers': EnvironHeaders([('Authorization', testkey:'), ('Host', u'test'), ('Content-Length', u'81'), ('Content-Type', u'application/json')]),
 'shallow': False,
 'url': u'http://test/v1/test',
 'url_rule': <Rule '/v1/test' (POST, OPTIONS) -> testresource>,
 'view_args': {}}
like image 575
Patrick Yan Avatar asked Dec 24 '14 00:12

Patrick Yan


3 Answers

The request.authorization attribute is only set when you have a valid Basic Authorization or Digest Authorization header; the Authorization header has specific formats where the first word in the header value sets the type, and the attribute only handles those two specific types (flagged by the Basic or Digest type keywords).

From the AuthorizationMixin.authorization attribute documentation

The Authorization object in parsed form.

following that to the Authorization object docs:

Represents an Authorization header sent by the client. You should not create this kind of object yourself but use it when it’s returned by the parse_authorization_header function.

which is documented as:

Parse an HTTP basic/digest authorization header transmitted by the web browser. The return value is either None if the header was invalid or not given, otherwise an Authorization object.

Bold emphasis mine.

Your header is not such a valid header; it is doesn't have the Basic or Digest type indicator. If you did have such a header the function returns something other than None:

>>> from werkzeug.http import parse_authorization_header
>>> parse_authorization_header('testkey:')
>>> parse_authorization_header('testkey:') is None
True
>>> parse_authorization_header('Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==')
{'username': 'Aladdin', 'password': 'open sesame'}
>>> result = _
>>> type(result)
<class 'werkzeug.datastructures.Authorization'>
>>> result.username
'Aladdin'
>>> result.password
'open sesame'

I used a Basic type header there, where the remainder of the header value is a base-64 encoded username and password pair separated by a : colon.

If you want to implement your own authentication scheme, just access the header itself and parse it manually.

auth = request.headers.get('authorization')
like image 74
Martijn Pieters Avatar answered Oct 23 '22 20:10

Martijn Pieters


Your authorization header ('Authorization', 'testkey:') needs to be Base64 encoded and include Basic.

in python:

import base64
base64.b64encode('testkey:') # 'dGVzdGtleTo='

in javascript set your header using btoa:

'{"Authorization": "Basic ' + btoa('testkey:') + '"}' 
'{"Authorization": "Basic dGVzdGtleTo="}' 

In your case, the this will result in the header coming in as:

('Authorization', 'Basic dGVzdGtleTo=')

like image 11
Riley Avatar answered Oct 23 '22 20:10

Riley


When using apache+WSGI, don't forget the WSGIPassAuthorization On directive.

like image 10
caffeinate_me Avatar answered Oct 23 '22 20:10

caffeinate_me