I am recreating a service in Python/Flask and am running into an issue with the way the existing clients authenticate. I have to match the existing clients scheme for compatibility reasons.
The existing clients take the username, password and base64 encode it. This is not HTTP Basic Authentication, despite sounding similar. Below is some sample code that would create this login request.
credentials = {
'username': '[email protected]',
'password': 'password'
}
data = b64encode(urlencode(credentials))
request = urllib2.Request(loginURL)
request.add_data(data)
# request.add_header('Content-Type', 'application/gooblygop')
# 'application/x-www-form-urlencoded' seems to be a default Content-Type
login = urllib2.urlopen(request)
On the server side, I take the POST data and base64 decode it to get the username and password information again.
flask server:
@app.route('/login', methods=['POST'])
def login():
error = None
if request.method == 'POST':
# post data: cGFzc3dvcmQ9ZGVmYXVsdCZlbWFpbD10ZXN0JTQwZXhhbXBsZS5jb20=
data = b64decode(request.data)
# decoded data: password=default&email=test%40example.com
return('ok')
The problem is the Content Type. If I specify an unknown Content-Type in the client (application/gooblygop), Flask exposes the POST data to request.data and I can decode the base64 string. If I leave the Content-Type as default (application/x-www-form-urlencoded), the raw data is not exposed to request.data and I don't know how to retrieve the base64 encoded string and make use of it.
The existing client software all pretty much defaults to x-www-form-urlencoded, but I can't rely on that always being the case.
Essentially, I need a reliable, server-side method for accessing that encoded string no matter what Content-Type the client program states.
Other notes: I am very new to Python, coming from a PHP background. So I am very open to suggestions. Also, this project is primarily for personal use.
You want to look at the request.form
object when dealing with urlencoded posts with normal mimetypes. In this case you have an unusual form, but here is a way to do it:
# mkreq.py
from urllib import urlencode
import urllib2
from base64 import b64encode
credentials = {
'username': '[email protected]',
'password': 'password'
}
data = b64encode(urlencode(credentials))
request = urllib2.Request("http://localhost:5000/login")
request.add_data(data)
request.add_header('Content-Type', 'application/gooblygop')
# 'application/x-www-form-urlencoded' seems to be a default Content-Type
login1 = urllib2.urlopen(request).read()
print(login1)
request2 = urllib2.Request("http://localhost:5000/login")
request2.add_data(data)
login2 = urllib2.urlopen(request2).read()
print(login2)
You probably want to modify the login bit to check the mimetype, here is a version with minimal changes to your current setup:
@app.route('/login', methods=['POST'])
def login():
error = None
if request.method == 'POST':
# post data: cGFzc3dvcmQ9ZGVmYXVsdCZlbWFpbD10ZXN0JTQwZXhhbXBsZS5jb20=
data = b64decode(request.data)
# decoded data: password=default&email=test%40example.com
if not data:
data = b64decode(request.form.keys()[0])
special_mimetype = request.mimetype
return(special_mimetype + '\n' + data)
This is the output of the first code sample, with two requests:
bvm$ python mkreq.py
application/gooblygop
username=test%40example.com&password=password
application/x-www-form-urlencoded
username=test%40example.com&password=password
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With