Reputation: 81
I am trying to write some REST APIs in python, to begin with I started to write Authenticate code. I found sample code for authenticate on one of the site:
from functools import wraps
from flask import request, Response
def check_auth(username, password):
"""This function is called to check if a username /
password combination is valid.
"""
return username == 'admin' and password == 'secret'
def authenticate():
"""Sends a 401 response that enables basic auth"""
return Response(
'Could not verify your access level for that URL.\n'
'You have to login with proper credentials', 401,
{'WWW-Authenticate': 'Basic realm="Login Required"'})
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(username, password):
return authenticate()
return f(*args, **kwargs)
return decorated
I have used the above piece of code to secure my sample app:
@app.route('/student/<studentid>', methods = ['GET'])
@requires_auth
def api_users(studentid):
students = {'1':'ABC', '2':'XYZ', '3':'TEST'}
if studentid in students:
return jsonify({studentid:students[studentid]})
else:
return not_found()
Now, I am trying to call this url through python requests/pycurl module. But, everytime it returns the 401 error irrespective of valid username/password.
using requests:
import requests, base64
usrPass = "admin:secret"
b64Val = base64.b64encode(usrPass)
from requests.auth import HTTPBasicAuth
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
res = requests.get('https://<abc.com>/student/1', auth=HTTPBasicAuth('admin','secret'), headers={'Authorization': 'Basic %s' % b64Val}, data={}, verify=False)
print res
using curl:
myCurlPut = pycurl.Curl()
myCurlPut.setopt(pycurl.URL, "https://<abc.com>/student/1")
myCurlPut.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC)
myCurlPut.setopt(pycurl.USERPWD, "%s:%s" % ('admin', 'secret'))
myCurlPut.setopt(pycurl.SSL_VERIFYPEER, 0)
myCurlPut.setopt(pycurl.HTTPHEADER, ['X-HTTP-Method-Override: GET'])
myCurlPut.perform()
Can, anyone please help me why everytime it returns the 401 error. Please suggest.
Upvotes: 3
Views: 1220
Reputation: 1358
This is a working example of flask-authorization.
from functools import wraps
from flask import Flask,Response,request, abort
app = Flask(__name__)
def check_auth(name,passw):
return (name=='admin' and passw=='pass')
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
abort(401)
return f(*args, **kwargs)
return decorated
@app.route('/')
@requires_auth
def hello():
return "Hello World"
if __name__ == "__main__":
app.run(debug=True)
My requests file:
import requests, base64
usrPass = "admin:pass"
b64Val = base64.b64encode(usrPass)
from requests.auth import HTTPBasicAuth
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
res = requests.get('http://127.0.0.1:5000/', auth=HTTPBasicAuth('admin','pass'), headers={'Authorization': 'Basic %s' % b64Val}, data={}, verify=False)
print res
If you are running this on localhost you should use the localhost address.
What is <abc.com>
in your code.Probably that is the error.
EDIT 2
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer, BadSignature, SignatureExpired
def gen_token(name,passw, expiration=None):
s = Serializer(app.config['SECRET_KEY'], expires_in = expiration)
return s.dumps(name, passw)
def verify_token(token):
serial = Serializer(app.config['SECRET_KEY'])
try:
data = serial.loads(token)
except BadSignature:
return "Error"
except SignatureExpired:
return "Error"
name = data[0]
passw = data[1]
return name,passw
These are couple of methods that will help you get started with the token based auth.
What I did was
username
and password
is correct you can generate the token using gen_token
method. You can modify this method according to your requirments. Read Hereusername
. password
can be left blank or send None
in that place.SECRET_KEY
.Exceptions can be handled as per your requirements. If the token is valid you will be able to obtain the user who sent the request and thus carry your procedure.Hope it helps!
Check out this link for a more detailed explanation.
Upvotes: 1
Reputation: 103
Looks like you are not passing username and password correctly to authenticate. Value of username
and password
you should get from the auth
variable. So try changing the requires_auth
funtion as:
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
return authenticate()
return f(*args, **kwargs)
return decorated
Upvotes: 0