I am using token based authentication to restrict the access to user for my site, I am getting following error
{"_status": "ERR", "_error": {"message": "Please provide proper credentials", "code": 401}}weber#weber-desktop:/var/www/lunar-cloud-web-ui/kukunako$
my sample code shown below.
class TokenAuth(TokenAuth):
def check_auth(self, token, allowed_roles, resource, method):
accounts = app.data.driver.db['people']
return accounts.find_one({'token': token})
app = Eve(__name__,static_url_path='/static', auth = TokenAuth)
app.debug = True,
app.config.update(
DEBUG=True,
#EMAIL SETTINGS
MAIL_SERVER='smtp.gmail.com',
MAIL_PORT=465,
MAIL_USE_SSL=True,
MAIL_USERNAME = '<username>',
MAIL_PASSWORD = '<password>'
)
mail=Mail(app)
socketio = SocketIO(app)
def create_token(user):
payload = {
'sub': str(user['_id']),
'iat': datetime.now(),
'exp': datetime.now() + timedelta(days=14)
}
token = jwt.encode(payload, TOKEN_SECRET)
return token.decode('unicode_escape')
def login_required(f):
#wraps(f)
def decorated_function(*args, **kwargs):
if not request.headers.get('Authorization'):
response = jsonify(error='Missing authorization header')
response.status_code = 401
return response
payload = parse_token(request)
if datetime.fromtimestamp(payload['exp']) < datetime.now():
response = jsonify(error='Token has expired')
response.status_code = 401
return response
g.user_id = payload['sub']
return f(*args, **kwargs)
return decorated_function
#app.route('/auth/login', methods=['POST'])
def login():
accounts = app.data.driver.db['people']
user = accounts.find_one({'email': request.json['email']})
if not user:
response = jsonify(error='Your email does not exist')
response.status_code = 401
return response
if not user['email_confirmed'] == True:
response = jsonify(error='Email is not confirmed')
response.status_code = 401
return response
if not user or not check_password_hash(user['password']['password'], request.json['password']):
response = jsonify(error='Wrong Email or Password')
response.status_code = 401
return response
token = create_token(user)
return jsonify(token=token)
my all code is show in following for settings file and server code file
settings file
server code file
How are you testing it?
I can think of two possible problems.
JWT token needs to be base64 encoded
You may have forgotten : at the end
e.g. If your token is as follows (Taken from jwt.io site)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
You need to do the following:
$ echo 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ:' | base64
ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnpkV0lpT2lJeE1qTTBOVFkzT0Rrd0lpd2libUZ0WlNJNklrcHZhRzRnUkc5bElpd2lZV1J0YVc0aU9uUnlkV1Y5LlRKVkE5NU9yTTdFMmNCYWIzMFJNSHJIRGNFZnhqb1laZ2VGT05GaDdIZ1E6Cg==
Now use this as follows (with curl)
curl -H "Authorization Basic ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnpkV0lpT2lJeE1qTTBOVFkzT0Rrd0lpd2libUZ0WlNJNklrcHZhRzRnUkc5bElpd2lZV1J0YVc0aU9uUnlkV1Y5LlRKVkE5NU9yTTdFMmNCYWIzMFJNSHJIRGNFZnhqb1laZ2VGT05GaDdIZ1E6Cg==" http://127.0.0.1:5000/my_secure_endpoint
Related
I was trying to create a flask app with user-login API call that generates access and refresh token and upon successful creation redirect back to homepage view which has jwt_required(optional=True) decorator but no matter how i try to save the token i'm unable to fetch it via get_jwt()
This is the API for generating the access and refresh token.
class UserLogin(MethodResource, Resource):
#doc(description='This is User Login Endpoint', tags=['User Endpoint'])
#use_kwargs(User_RequestSchema(exclude=("name", "email","admin")))
#marshal_with(Login_ResponseToken, code=200, description="Success | Returns: \nUser Registered Succesfully")
#marshal_with(Msg_ResponseSchema, code=401, description="Unauthorized | Returns: \n-Invalid User Credentials!")
#marshal_with(Msg_ResponseSchema, code=400, description="Bad Request | Returns: \n-Error loading Json body on request")
def post(self,**kwargs):
"""
If user roll_num and password correct create a new access and refresh token
else return invalid credentials 401 error
"""
try:
schema = User_RequestSchema(exclude=("name", "email","admin"))
data = schema.load(kwargs,unknown=EXCLUDE)
except:
output = {"message":"Error loading Json body in request"}
return output, 400 #Status-Bad Request
user = UserModel.find_by_rollnum(data['roll_num'])
# User Present and password correct
if user is not None and user.check_password(data['password']) and user.roll_num==data['roll_num']:
additional_claims = {"admin_access":user.admin}
access_token = create_access_token(identity=user.roll_num, additional_claims=additional_claims,fresh=True)
refresh_token = create_refresh_token(user.roll_num)
resp = jsonify(login=True)
set_access_cookies(resp, access_token.encode('utf-8'))
set_refresh_cookies(resp, refresh_token.encode('utf-8'))
resp.set_cookie('X-CSRF-TOKEN-ACCESS', access_token.encode('utf-8'))
resp.set_cookie('X-CSRF-TOKEN-REFRESH', refresh_token.encode('utf-8'))
output={"access_token":access_token,
"refresh_token":refresh_token,
"message": "Successful Login"}
return output, 200 # Status-OK
output = {"message": "Invalid User Credentials!"}
return output, 401 # Status-Unauthorized
This is the code that calls the login API and provides login information from login Form
#auth.route("/user_login", methods=["GET", "POST"])
def user_login():
form = LoginForm()
if form.validate_on_submit():
data = {"roll_num": form.roll_num.data,
"password": form.password.data}
# send request to login API
headers = CaseInsensitiveDict()
headers["Accept"] = "application/json"
headers["Content-Type"] = "application/json"
headers["Authorization"] = "Bearer {token}"
r = requests.post('http://localhost:5000/login', json=data, headers=headers)
if r.status_code==401:
flash("Wrong Roll Number or Password")
elif r.status_code==200:
print("Login correct")
flash("Log In successful")
access_token = r.json()['access_token']
resp = redirect(url_for('home.index'),access_token)
resp.headers = {'Authorization': 'Bearer {}'.format(access_token)}
return resp
print('Login_response',r)
print('Status Code',r.status_code)
print('data',r.text)
return render_template("login.html", form=form)
This is where the login should redirect on successful token generation
#home.route('/')
#home.route('/index')
#jwt_required(optional=True, locations=['headers', 'cookies'])
def index():
logged_in = 0
admin = 0
head = get_jwt_header()
print(head)
identity = get_jwt_identity()
print(identity)
claims = get_jwt()
print('claims:', claims)
if len(claims)!=0:
logged_in = 1
# If user is admin give ability to register
if claims['admin_access']==1:
admin = 1
print("Logged In: ", logged_in)
print("Admin: ", admin)
return render_template('index.html', admin=admin, logged_in=logged_in)
As far as I read should be able to get jwt claims and identity form the stored token, but no matter what I do i can't get this to work. It works in post man through assignment in environment variable. I can't figure out what I'm doing wrong?
I implemented auth0 quickstart python 01-login with my Flask Application and am receiving this response:
{ "message": "mismatching_state: CSRF Warning! State not equal in request and response." }
Here is a snippet of that code logic:
from models import setup_db, Bay, db_drop_and_create_all
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
from jinja2 import Environment, PackageLoader
from flask import Flask, render_template, request, Response, flash, redirect, url_for, jsonify, abort,session
from sqlalchemy import Column, String, Integer, create_engine,and_
from auth import AuthError, requires_auth
from functools import wraps
from os import environ as env
from werkzeug.exceptions import HTTPException
from dotenv import load_dotenv, find_dotenv
from authlib.integrations.flask_client import OAuth
from six.moves.urllib.parse import urlencode
import json
import constants
ENV_FILE = find_dotenv()
if ENV_FILE:
load_dotenv(ENV_FILE)
AUTH0_CALLBACK_URL = env.get(constants.AUTH0_CALLBACK_URL)
AUTH0_CLIENT_ID = env.get(constants.AUTH0_CLIENT_ID)
AUTH0_CLIENT_SECRET = env.get(constants.AUTH0_CLIENT_SECRET)
AUTH0_DOMAIN = env.get(constants.AUTH0_DOMAIN)
AUTH0_BASE_URL = 'https://' + AUTH0_DOMAIN
AUTH0_AUDIENCE = env.get(constants.AUTH0_AUDIENCE)
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__)
oauth = OAuth(app)
auth0 = oauth.register(
'auth0',
client_id=AUTH0_CLIENT_ID,
client_secret=AUTH0_CLIENT_SECRET,
api_base_url=AUTH0_BASE_URL,
access_token_url=AUTH0_BASE_URL + '/oauth/token',
authorize_url=AUTH0_BASE_URL + '/authorize',
client_kwargs={
'scope': 'openid profile email',
},
)
app.secret_key = constants.SECRET_KEY
app.debug = True
configedDB = setup_db(app)
if not configedDB:
abort(500)
#app.errorhandler(Exception)
def handle_auth_error(ex):
response = jsonify(message=str(ex))
response.status_code = (ex.code if isinstance(ex, HTTPException) else 500)
return response
'''
#TODO: Set up CORS. Allow '*' for origins. Delete the sample route after completing the TODOs
'''
CORS(app, resources={r"/api/*": {"origins": "*"}})
'''
#TODO: Use the after_request decorator to set Access-Control-Allow
'''
#app.after_request
def after_request(response):
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization,true')
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
return response
#----------------------------------------------------------------------------#
# Controllers.
#----------------------------------------------------------------------------#
#app.route('/')
def index():
return render_template('index.html')
#app.route('/callback')
def callback_handling():
#auth0 = app.config['auth0']
token = auth0.authorize_access_token()
resp = auth0.get('userinfo')
userinfo = resp.json()
print('>>>USER_INFO',userinfo)
session[constants.JWT_PAYLOAD] = userinfo
session[constants.PROFILE_KEY] = {
'user_id': userinfo['sub'],
'name': userinfo['name'],
'picture': userinfo['picture']
}
return redirect('/manager/bay/all')
#app.route('/login')
def login():
#auth0 = app.config['auth0']
#state = uuid.uuid4().hex
#redirect_url = url_for("auth.callback", _external=True)
#auth0.save_authorize_state(redirect_uri=redirect_url, state=state)
return auth0.authorize_redirect(redirect_uri=AUTH0_CALLBACK_URL, audience=AUTH0_AUDIENCE) #, state=state
#app.route('/logout')
def logout():
session.clear()
params = {'returnTo': url_for('home', _external=True), 'client_id': AUTH0_CLIENT_ID}
return redirect(auth0.api_base_url + '/v2/logout?' + urlencode(params))
Please note that for my .env file I have:
AUTH0_CLIENT_ID='l6yng5LFtKZIFZ6I56XXXXXXXX'
AUTH0_DOMAIN='double-helixx.us.auth0.com'
AUTH0_CLIENT_SECRET='egP3YRyAqtnHjtIkmnzWMPC0btJ3oN-odV001t9pgbKvc6nlT96PPrYsVeJzxTce'
AUTH0_CALLBACK_URL='http://127.0.0.1:5000/callback'
AUTH0_AUDIENCE='MYIMAGE'
Maybe this is the cause of the error from my side?
Python Samples Failing Out of the Box
authlib/issues
authlib-client-error-state-not-equal-in-request-and-response
It seems this is a recent issue for some people as well shown in here:
https://github.com/auth0-samples/auth0-python-web-app/issues/58
My auth0 Urls are:
I have an auth.py file as well that I have implemented- that may be the cause of the error?
import json
from flask import request, _request_ctx_stack
from functools import wraps
from jose import jwt
from urllib.request import urlopen
AUTH0_DOMAIN = 'double-helixx.us.auth0.com'
ALGORITHMS = ['RS256']
API_AUDIENCE = 'image'
## AuthError Exception
'''
AuthError Exception
A standardized way to communicate auth failure modes.
'''
class AuthError(Exception):
def __init__(self, error, status_code):
self.error = error
self.status_code = status_code
## Auth Header
'''
# implement get_token_auth_header() method
it should attempt to get the header from the request
it should raise an AuthError if no header is present
it should attempt to split bearer and the token
it should raise an AuthError if the header is malformed
return the token part of the header
'''
def get_token_auth_header():
"""Obtains the Access Token from the Authorization Header
"""
auth = request.headers.get('Authorization', None)
if not auth:
raise AuthError({
'code': 'authorization_header_missing',
'description': 'Authorization header is expected.'
}, 401)
parts = auth.split()
if parts[0].lower() != 'bearer':
raise AuthError({
'code': 'invalid_header',
'description': 'Authorization header must start with "Bearer".'
}, 401)
elif len(parts) == 1:
raise AuthError({
'code': 'invalid_header',
'description': 'Token not found.'
}, 401)
elif len(parts) > 2:
raise AuthError({
'code': 'invalid_header',
'description': 'Authorization header must be bearer token.'
}, 401)
token = parts[1]
return token
'''
# implement check_permissions(permission, payload) method
#INPUTS
permission: string permission (i.e. 'post:drink')
payload: decoded jwt payload
it should raise an AuthError if permissions are not included in the payload
!!NOTE check your RBAC settings in Auth0
it should raise an AuthError if the requested permission string is not in the payload permissions array
return true otherwise
'''
def check_permissions(permission, payload):
if 'permissions' not in payload:
raise AuthError({
'code': 'invalid_claims',
'description': 'Permissions not included in JWT.'
}, 400)
if permission not in payload['permissions']:
raise AuthError({
'code': 'unauthorized',
'description': 'Permission not found.'
}, 403)
return True
'''
# implement verify_decode_jwt(token) method
#INPUTS
token: a json web token (string)
it should be an Auth0 token with key id (kid)
it should verify the token using Auth0 /.well-known/jwks.json
it should decode the payload from the token
it should validate the claims
return the decoded payload
!!NOTE urlopen has a common certificate error described here: https://stackoverflow.com/questions/50236117/scraping-ssl-certificate-verify-failed-error-for-http-en-wikipedia-org
'''
def verify_decode_jwt(token):
jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json')
jwks = json.loads(jsonurl.read())
unverified_header = jwt.get_unverified_header(token)
rsa_key = {}
if 'kid' not in unverified_header:
raise AuthError({
'code': 'invalid_header',
'description': 'Authorization malformed.'
}, 401)
for key in jwks['keys']:
if key['kid'] == unverified_header['kid']:
rsa_key = {
'kty': key['kty'],
'kid': key['kid'],
'use': key['use'],
'n': key['n'],
'e': key['e']
}
if rsa_key:
try:
payload = jwt.decode(
token,
rsa_key,
algorithms=ALGORITHMS,
audience=API_AUDIENCE,
issuer='https://' + AUTH0_DOMAIN + '/'
)
return payload
except jwt.ExpiredSignatureError:
raise AuthError({
'code': 'token_expired',
'description': 'Token expired.'
}, 401)
except jwt.JWTClaimsError:
raise AuthError({
'code': 'invalid_claims',
'description': 'Incorrect claims. Please, check the audience and issuer.'
}, 401)
except Exception:
raise AuthError({
'code': 'invalid_header',
'description': 'Unable to parse authentication token.'
}, 400)
raise AuthError({
'code': 'invalid_header',
'description': 'Unable to find the appropriate key.'
}, 400)
'''
#TODO implement #requires_auth(permission) decorator method
#INPUTS
permission: string permission (i.e. 'post:drink')
it should use the get_token_auth_header method to get the token
it should use the verify_decode_jwt method to decode the jwt
it should use the check_permissions method validate claims and check the requested permission
return the decorator which passes the decoded payload to the decorated method
'''
def requires_auth(permission=''):
def requires_auth_decorator(f):
#wraps(f)
def wrapper(*args, **kwargs):
token = get_token_auth_header()
payload = verify_decode_jwt(token)
check_permissions(permission, payload)
return f(payload, *args, **kwargs)
return wrapper
return requires_auth_decorator
Any ideas?
Package versioning
Flask 1.0.2
Flask-HTTPAuth 3.2.4
Flask-RESTful 0.3.8
itsdangerous 0.24
I'm working on a API project where a POST request to a Todo resource requires an user to have a token. Upon trying to test for this scenario, I'm getting the following assertion error: AssertionError: 401 != 201. Both BasicHTTPAuth and TokenHTTPAutth from flask-HTTPAuth are handling Authorization credentials.
Based on a User having a token to access this resource, I'm not clear on why I'm getting an Unauthorized error.
tests.py
class TestAuthenicatedUserPostTodo(ApiTestCase):
'''Verify that an API user successfully adds a Todo'''
def setUp(self):
super().setUp()
previous_todo_count = Todo.select().count()
user = User.get(User.id == 1)
token_serializer = Serializer(SECRET_KEY)
self.token = token_serializer.dumps({'id': user.id})
def test_todo_collection_post_todo_success(self):
with app.test_client() as client:
http_response = client.post(
"/api/v1/todos/",
headers={
'Authorization': f"Bearer {self.token}"
},
content_type="application/json",
data={
"name": "Must do a todo",
"user": 1
}
)
current_todo_count = Todo.select().count()
self.assertEqual(http_response.status_code, 201)
self.assertGreater(current_todo_count, previous_todo_count)
auth.py
basic_auth = HTTPBasicAuth()
token_auth = HTTPTokenAuth(scheme="Bearer")
auth = MultiAuth(token_auth, basic_auth)
#basic_auth.verify_password
def verify_password(username, password):
try:
api_user = User.get(User.username == username)
except User.DoesNotExist:
return False
user_verified = api_user.check_password(password)
if user_verified:
g.user = api_user
return True
return False
#token_auth.verify_token
def verify_token(token):
timed_serializer = Serializer(SECRET_KEY)
try:
user = timed_serializer.loads(token)
api_user = User.get_by_id(user['id'])
except (SignatureExpired, BadSignature) as e:
abort(400, description=str(e))
return True
todo.py
#auth.error_handler
def errorhandler():
return jsonify(unauthorized="Cannot add Todo. Login required."), 401
class TodoCollection(Resource):
#auth.login_required
def post(self):
import pdb; pdb.set_trace()
args = self.request_parser.parse_args()
if not args['name']:
return make_response(
{'invalid_request': "Invalid todo provided"}, 400
)
new_todo = Todo.create(**args)
return (
marshal(set_todo_creator(new_todo), todo_fields, 'new_todo'),
201, {'Location': f'{new_todo.location}'}
)
Using the following code, I've setup a flask app:
https://gist.github.com/ugik/a218a599b1af0ea06b1b38e3a5132078#file-flaskfbmapi-ai-rig
import requests
import json
from flask import Flask, request
import apiai
# FB messenger credentials
ACCESS_TOKEN = "EAAKsKOJ37rUBAKVZAQ21bn...UsZCXx6UWqQ6XuQr7OHnBYL3xD3Sy5u1ZAZCwip0XnTAHq25CsIpxRsbxZALRHOOguKm2unY7I06LRAZDZD"
# api.ai credentials
CLIENT_ACCESS_TOKEN = "78c0e0...d9404a2"
ai = apiai.ApiAI(CLIENT_ACCESS_TOKEN)
app = Flask(__name__)
#app.route('/', methods=['GET'])
def verify():
# our endpoint echos back the 'hub.challenge' value specified when we setup the webhook
if request.args.get("hub.mode") == "subscribe" and request.args.get("hub.challenge"):
if not request.args.get("hub.verify_token") == 'foo':
return "Verification token mismatch", 403
return request.args["hub.challenge"], 200
return 'Hello World (from Flask!)', 200
def reply(user_id, msg):
data = {
"recipient": {"id": user_id},
"message": {"text": msg}
}
resp = requests.post("https://graph.facebook.com/v2.6/me/messages?access_token=" + ACCESS_TOKEN, json=data)
print(resp.content)
#app.route('/', methods=['POST'])
def handle_incoming_messages():
data = request.json
sender = data['entry'][0]['messaging'][0]['sender']['id']
message = data['entry'][0]['messaging'][0]['message']['text']
# prepare API.ai request
req = ai.text_request()
req.lang = 'en' # optional, default value equal 'en'
req.query = message
# get response from API.ai
api_response = req.getresponse()
responsestr = api_response.read().decode('utf-8')
response_obj = json.loads(responsestr)
if 'result' in response_obj:
response = response_obj["result"]["fulfillment"]["speech"]
reply(sender, response)
return "ok"
if __name__ == '__main__':
app.run(debug=True)
However, at line 51 there is an error in my server logs:
UnboundLocalError: local variable 'response' referenced before
assignment
Which I understand the root of the cause is "response" is defined only within the if statement, however, since it is not my code, I'm having trouble defining the variable outside. Will this work if I place this code after line 48:
response = response_obj["result"]["fulfillment"]["speech"]
Hi!
I have a route that I have protected using HTTP Basic authentication, which is implemented by Flask-HTTPAuth. Everything works fine (i can access the route) if i use curl, but when unit testing, the route can't be accessed, even though i provide it with the right username and password.
Here are the relevant code snippets in my testing module:
class TestClient(object):
def __init__(self, app):
self.client = app.test_client()
def send(self, url, method, data=None, headers={}):
if data:
data = json.dumps(data)
rv = method(url, data=data, headers=headers)
return rv, json.loads(rv.data.decode('utf-8'))
def delete(self, url, headers={}):
return self.send(url, self.client.delete, headers)
class TestCase(unittest.TestCase):
def setUp(self):
app.config.from_object('test_config')
self.app = app
self.app_context = self.app.app_context()
self.app_context.push()
db.create_all()
self.client = TestClient(self.app)
def test_delete_user(self):
# create new user
data = {'username': 'john', 'password': 'doe'}
self.client.post('/users', data=data)
# delete previously created user
headers = {}
headers['Authorization'] = 'Basic ' + b64encode((data['username'] + ':' + data['password'])
.encode('utf-8')).decode('utf-8')
headers['Content-Type'] = 'application/json'
headers['Accept'] = 'application/json'
rv, json = self.client.delete('/users', headers=headers)
self.assertTrue(rv.status_code == 200) # Returns 401 instead
Here are the callback methods required by Flask-HTTPAuth:
auth = HTTPBasicAuth()
#auth.verify_password
def verify_password(username, password):
# THIS METHOD NEVER GETS CALLED
user = User.query.filter_by(username=username).first()
if not user or not user.verify_password(password):
return False
g.user = user
return True
#auth.error_handler
def unauthorized():
response = jsonify({'status': 401, 'error': 'unauthorized', 'message': 'Please authenticate to access this API.'})
response.status_code = 401
return response
Any my route:
#app.route('/users', methods=['DELETE'])
#auth.login_required
def delete_user():
db.session.delete(g.user)
db.session.commit()
return jsonify({})
The unit test throws the following exception:
Traceback (most recent call last):
File "test_api.py", line 89, in test_delete_user
self.assertTrue(rv.status_code == 200) # Returns 401 instead
AssertionError: False is not true
I want to emphazise once more that everything works fine when i run curl with exactly the same arguments i provide for my test client, but when i run the test, verify_password method doesn't even get called.
Thank you very much for your help!
Here is an example how this could be done with pytest and the inbuilt monkeypatch fixture.
If I have this API function in some_flask_app:
from flask_httpauth import HTTPBasicAuth
app = Flask(__name__)
auth = HTTPBasicAuth()
#app.route('/api/v1/version')
#auth.login_required
def api_get_version():
return jsonify({'version': get_version()})
I can create a fixture that returns a flask test client and patches the authenticate function in HTTPBasicAuth to always return True:
import pytest
from some_flask_app import app, auth
#pytest.fixture(name='client')
def initialize_authorized_test_client(monkeypatch):
app.testing = True
client = app.test_client()
monkeypatch.setattr(auth, 'authenticate', lambda x, y: True)
yield client
app.testing = False
def test_settings_tracking(client):
r = client.get("/api/v1/version")
assert r.status_code == 200
You are going to love this.
Your send method:
def send(self, url, method, data=None, headers={}):
pass
Your delete method:
def delete(self, url, headers={}):
return self.send(url, self.client.delete, headers)
Note you are passing headers as third positional argument, so it's going as data into send().