Django - Transforming Form data to REST API, POST request - django

Given an arbitrary html form, what is the fastest and smoothest way of transforming the entered data to a REST API JSON POST request to an arbitrary address?
Are there any good libraries for this in Django?
Thanks

The simplest would be to use requests.
Code example for login would be:
import requests
def user_login(request):
# If token was already acquired, redirect to home page
if request.session.get('api_token', False):
return HttpResponseRedirect(reverse('index'))
# Get username and password from posted data, authenticate and
# if successful save api token to session
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
r = requests.post('http://localhost/api-token-auth/', data={'username': username, 'password': password})
if r.status_code == 200:
response = r.json()
token = response['token']
# Save token to session
request.session['api_token'] = token
else:
messages.error(request, 'Authentication failed')
return HttpResponseRedirect(reverse('login'))
else:
return render(request, 'login.html', {})
That's just a simple example. The key is this part:
r = requests.post('http://localhost/api-token-auth/', data={'username': username, 'password': password})

Related

Flask-login causing login form to not validate

The login form of my flask app is failing to validate (form.valididate = false) when the app has automatically logged users out:
app.permanent_session_lifetime = timedelta(minutes=5)
form.errors returns an empty dictionary {}.
Any ideas what is going on?
Login route below. When the user has been automatically logged out the code beneath 'if form.validate_on_submit...' is completely bypassed.
#view.route('/Login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated and current_user.is_suspended != True:
return redirect(url_for('view.Index'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is None or not user.check_password(form.password.data):
flash('Invalid username or password')
return redirect(url_for('view.login'))
if user.is_suspended and user.check_password(form.password.data):
flash('Your login has been suspended. Please contact NZGBC.')
return redirect(url_for('view.login'))
user.session_token = user.generate_session_token()
db.session.commit()
login_user(user, remember=form.remember_me.data)
if form.remember_me.data is not True:
app.permanent_session_lifetime = timedelta(minutes=60)
else:
app.permanent_session_lifetime = timedelta(days=365)
next = request.args.get('next')
# is_safe_url should check if the url is safe for redirects.
# See http://flask.pocoo.org/snippets/62/ for an example.
if not is_safe_url(next):
return abort(400)
return redirect(next or url_for('view.Index'))
return render_template('login.html', highlight='11', title='Sign In', form=form)
According to your comment:
Obliously after using the CSRF token for submitting a form it will fail, since CSRF tokens are 1-time use.
Try doing this as a workaround in your login route:
try:
if form.validate_on_submit():
# ... process your form normally ...
except:
return redirect(url_for('view.login'))
# ... maybe display a message for the user to reenter his creds because he was logged out ...
This should work as a viable fix for your problem.

Django csrf_protect decorator not working

I am using Django to build a web app. I am using Vue JS for the frontend. My problem is when ever I use csrf_protect its showing 403 error
My views:
#csrf_protect
def SignUpView(request):
if request.method == "POST":
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
username, password = form.cleaned_data.get('username'), form.cleaned_data.get('password1')
new_user = authenticate(username = username, password = password)
login(request, new_user)
return redirect('/')
else:
form = SignUpForm()
return render(request, 'Accounts/SignUp.html', {'form':form})
#csrf_protect
def validateUsername(request):
username = request.GET.get('username', None)
usernameRegEx = r'^[a-zA-Z0-9#+-_.#]*$'
usernameRegExResult = {
'valid' : bool(re.search(usernameRegEx, username, re.M|re.I)),
'is_taken' : User.objects.filter(username=username).exists()
}
return JsonResponse(usernameRegExResult)
I read the Django docs which says I can use csrf_protect decorator above my view but in my case its not working. Somebody please help.
CSRF is a protection that prevents cross site request forgery. It works by generating an unique token that identify the form. So if you send data to your server without the token it gave you (through cookies for instance) it will not accept it.
If you have the CSRF middleware turned on you should not need CSRF protect decorator!

How can I set a persistent JWT token header in flask?

I can't seem to find a way to set the JWT Token as a header in each HTTP Request without the help of Javascript.
Currently I have my application setup to use the methods 'set_access_cookies' and 'unset_access_cookies' to keep track of the session. However, just unsetting the cookie does not invalidate the cookie. Therefore, I would like to use JWT in the header so that I can use the blacklist.add() method as blacklist.add() appears to not be able to look at cookies from my testing.
My Login function:
#app.route('/v1/login', methods=['POST', 'GET'])
def auth_user():
''' auth endpoint '''
if request.method == 'POST':
data = validate_user(request.get_json())
if data['ok']:
data = data['data']
user = mongo.db.users.find_one({'email': data['email']}, {"_id": 0})
if user and flask_bcrypt.check_password_hash(user['password'], data['password']):
access_token = create_access_token(identity=data)
refresh_token = create_refresh_token(identity=data)
resp = make_response(render_template('index.html'), 302)
set_access_cookies(resp, access_token)
return resp
else:
return jsonify({'ok': False, 'message': 'invalid username or password'}), 200
else:
return jsonify({'ok': False, 'message': 'invalid username or password'}), 200
elif request.method == 'GET':
return render_template('/api/v1/login.html')
My Logout function:
#app.route('/v1/logout', methods=['POST'])
def logout():
''' logout user endpoint '''
resp = jsonify({'logout': True})
unset_jwt_cookies(resp)
return resp, 200
This works fine, but is there an easy way to place the JWT as a persistent header instead?
I forgot to set 'JWT_COOKIE_CSRF_PROTECT' in my config so my POST request to logout was returning Unauthorized before it could be blacklisted.

django and angularJS permission_required anonymousUser

i'm writing a django / angularjs application, and i'm trying to use the #permission_required for user permission authorization.
I'm returning from the client side both headers- sessionId and csrf token, and yet the #permission_required method user, is anonymousUser, although when i'm logging in the user, i use - login(request, user) method, and the user arg is updated to the current user:
#api_view(['GET', 'POST', 'DELETE'])
def log_in_view(request):
body = request.body
json_body = json.loads(body)
email = json_body.get("email")
password = json_body.get('password')
user = authenticate(email=email, password=password)
session = request.session
if user is not None:
request.session['email'] = email
request.session['password'] = password
session.set_expiry(900)
session.save()
session_key = session.session_key
login(request, user)
crcf = get_token(request)
response_body = {}
response_body.update({"session_key" : session_key})
response_body.update({"csrf" : crcf})
return HttpResponse(json.dumps(response_body), content_type="text/json", status=200)
else:
return HttpResponse("could not authenticate user", content_type="text/plain", status=401)
does anyone have any idea what am i doing wrong?
cheers
you dont need all those stuff to login the user. I mean you dont need to set up session manually, either return csrf token.
#api_view(['GET', 'POST', 'DELETE'])
def log_in_view(request):
body = request.body
json_body = json.loads(body)
email = json_body.get("email")
password = json_body.get('password')
user = authenticate(email=email, password=password)
if user:
login(request, user)
response_body = {}
response_body['user'] = user
return HttpResponse(json.dumps(response_body), content_type="text/json", status=200)
else:
return HttpResponse("could not authenticate user", content_type="text/plain", status=401)
By use of #api_view I'm assuming that you're using Django REST Framework.
Each api view of django rest framework don't rely by default on django authentication. If you want your view to use django authentication, you should add proper #authentication_classes(...) decorator to your view or specify it globally in your settings.py file.

How to set cookie at user authentication in Django ?

Hey, can someone help me to set this cookie in django ;s Here is the code ;p
class MFAuthForm(AuthenticationForm):
def clean(self):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username and password:
self.user_cache = authenticate(username=username, password=password)
self.request.set_cookie("mfusername", username)
if self.user_cache is None:
raise forms.ValidationError(_("Please enter a correct username and password. Note that both fields are case-sensitive."))
elif not self.user_cache.is_active:
raise forms.ValidationError(_("This account is not yet active."))
elif self.user_cache.penalty > 1:
raise forms.ValidationError(_("For unfair treatment of the conditions of the site, MacroFactor has removed your account. To use the services of MacroFactor you need to register again. In subsequent registration please stick to the established rules. "))
# TODO: determine whether this should move to its own method.
if self.request:
if not self.request.session.test_cookie_worked():
raise forms.ValidationError(_("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in."))
return self.cleaned_data
I'll do it in the login view:
username = ''
if request.method == 'POST':
if form.is_valid():
username = form.cleaned_data['username']
response = render_to_response(...)
# if you are using redirect,
# response = redirect(...)
if username:
response.set_cookie("mfusername", username)
return response
You should set the cookie in the response, not the request.
http://docs.djangoproject.com/en/1.2/ref/request-response/#django.http.HttpResponse.set_cookie
You should se t the cookie wherever you are building the response (typically your view)