Django + Phonegap Authentication - python

I am building an application with Phonegap on the client side and a Django server on the backend. I am not able to authenticate the user. Here's my code.
$.ajax({
url: "http://192.168.0.101/userbase/login/",
type: "POST",
dataType: "json",
data: {"username": username,
"account": account,
"password": password,},
success: function (json) {
if (json.logged_in == true) {
window.location.href = "products.html";
}
else {
alert("Invalid Credentials. " + json.error);
}
}
});
This is the AJAX call to log in the user from the index.html. It is authenticated temporarily as in the views.py
# SOME CODE
login(request, user=user)
print(request.user.is_authenticated())
response = JsonResponse(response_data)
response['Access-Control-Allow-Origin'] = '*'
response['Access-Control-Allow-Methods'] = 'OPTIONS,GET,PUT,POST,DELETE'
response['Access-Control-Allow-Headers'] = 'X-Requested-With, Content-Type'
return response
prints True. But, when the window redirects to products.html and I make an AJAX request to my Django server and check if the user is authenticated or not, it returns False. I am not able to find the error.
Please help. Thanks.

Related

CSRF verification failed. Request aborted in Django rest framework sending the request from flutter

I've followed everything mentioned in both documentation of Django rest-framework and Flutter http but still getting the error ..here is my code :
Django
Settings
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
]
}
View
#csrf_exempt
#permission_classes(["isAuthenticated"])
#api_view(['POST'])
def chanage_image(request):
data = {}
if request.method == "POST":
token = request.META['HTTP_AUTHORIZATION'][6:]
lang = request.META['HTTP_LANG']
image = request.data['image']
main_user = Token.objects.get(key=token).user
app_user = AppUser.objects.get(main_user=main_user)
format, imgstr = image.split(';base64,')
ext = format.split('/')[-1]
data = ContentFile(base64.b64decode(imgstr), name='temp.' + ext) # You can save this as file instance.
app_user.image = data
app_user.save()
data = {"success": True, "details": AppUserSerializer(
app_user).data, "message": "Image changed" if lang == "en" else "تم تغيير الصورة"}
return Response(data, headers=get_headers())
URLS
path('chanage_image/', chanage_image,name="chanage_image"),
Flutter
Request
Map<String, dynamic> body = {
"image": base64Image,
};
Future<UserModel> changePlayerImage(Map<String, dynamic> body) async {
return await httpClient.post('api/user/change-image',
body: body,
headers: {'referer': 'https://www.l-dawri.com/'}).then((response) {
print(response.body);
return UserModel.fromJson(response.body);
});
}
but still in the end am always getting this error :
CSRF verification failed. Request aborted.
You are seeing this message because this site requires a CSRF cookie when submitting forms.
First you don't sent authorization token into header request while use from drf TokenAuthentication
Also into drf is better you use from class view api(like inheritance from APIView) replace def view's

Django-rest-framework api add SessionAuthentication as optional

Hi i'm currently have my api that use this simple-JWT package for jwt token authentication, it worked great. But now when i try to call the api from the django website app using Ajax in which is from a page user already logged in but it still required me to use the jwt access_token.
My ajax call from the page user already logged in:
$.ajax({
type: "POST",
url: "/api/add_favorite/" + property_id + "/",
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', 'Bearer {{ refresh_token }}');
},
success: function (data) {
if (data.code == 200) {
alert('added to favorite');
replace_part_1 = '<a id="mylink2" href="#" value="' + property_id +'"><i class="fas fa-heart fa-lg" style="color: red" title="Remove from favorite"></i></a>'
$("a[value='" + property_id + "']").replaceWith(replace_part_1);
}
}
});
Now i don't want to set the header with authorization since in the page user already logged in so the session is already set.
So i tried to add Django Session authentication to the the api like so:
#api_view(['POST'])
#authentication_classes([SessionAuthentication, JWTAuthentication])
#permission_classes([IsAuthenticated])
def add_favorite(request, property_id):
if request.method == 'POST':
try:
favorite_property = Property.objects.get(pk=property_id)
if request.user.is_authenticated:
login_user = request.user
if not login_user.properties.filter(pk=property_id).exists():
login_user.properties.add(favorite_property)
return JsonResponse({'code':'200','data': favorite_property.id}, status=200)
else:
return JsonResponse({'code':'404','errors': "Property already exists in favorite"}, status=404)
except Property.DoesNotExist:
return JsonResponse({'code':'404','errors': "Property not found"}, status=404)
My Ajax after removed the header :
$.ajax({
type: "POST",
url: "/api/add_favorite/" + property_id + "/",
},
success: function (data) {
if (data.code == 200) {
alert('added to favorite');
replace_part_1 = '<a id="mylink2" href="#" value="' + property_id +'"><i class="fas fa-heart fa-lg" style="color: red" title="Remove from favorite"></i></a>'
$("a[value='" + property_id + "']").replaceWith(replace_part_1);
}
}
});
and i removed the set header from the Ajax call now i get 403 return code :
Failed to load resource: the server responded with a status of 403
(Forbidden)
My settings:
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
# 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
I don't know why the session authentication doesn't work since the Ajax call is from the page user already logged in.
Thank for reading!
Because you're adding Authentication header on your ajax requests, Django automatically use TokenAuthentication if Authentication exists on the request header. Remove it to use SessionAuthentication.
There might be a problem when you're switch to use SessionAuthentication is that Django will reject your unsafe requests if there is no CSRF token, more detail here

How should a django app handle a post request from a reactjs form

I wrote a views function in my django app for user registration, the code for which is as follows:
def register(request):
if request.method == 'POST':
data1 = json.dumps(request.POST)
data = json.loads(data1)
full_name = data['userName']
company_name = data['agencyName']
phone = data['phoneNumber']
email_id = data['email']
password = data['password']
password2 = data['confirmpassword']
#Check if passwords match
if password == password2:
#Check username
if MyUser.objects.filter(email=email_id).exists():
messages.error(request,'That email is being used')
return redirect('register')
else:
#Looks good
user = MyUser.objects.create_user(password=password,
email=email_id, full_name=full_name,company_name=company_name,phone=phone)
user.save()
messages.success(request,'You are now registered')
return HttpResponse(json.dumps({'success':'success'}), content_type='application/json')
else:
messages.error(request,'Passwords donot match')
return HttpResponse(json.dumps({'error':'password donot match'}), content_type='application/json')
return HttpResponse(json.dumps({'none':'none'}),content_type='application/json')
The reactjs code is:
class SignupForm extends Component {
constructor(props) {
super(props);
this.state = {
userName: null,
agencyName: null,
email: null,
password: null,
confirmpassword: null,
phoneNumber: null,
formErrors: {
userName: "",
agencyName: "",
email: "",
password: "",
confirmpassword:"",
phoneNumber :""
}
};
}
handleSubmit = e => {
e.preventDefault();
if (formValid(this.state)) {
fetch('https://localhost:8000/accounts/register', {
method: 'POST',
body: this.state,
headers:{
// 'Access-Control-Allow-Origin':'*',
'Content-Type':'application/json',
}
});
} else {
console.error("FORM INVALID - DISPLAY ERROR MESSAGE");
}
};
The front-end of the website is made in reactjs and when I try to send a POST request from the react app for registration, it doesn't register's the user.
Also when I send a post request from postman to it for user registration it works fine and create the user. However when I try to send a json object from postman something like this
{'userName':'abcdef','phoneNumber':'123456789',email='abc#xyz.com','password':'1234','confirmpassword':'1234','agencyName':'abbb'}
it shows the following error:
KeyError at /accounts/register
'userName'
How should I resolve this? What are the ways through which I can handle a POST request in Django from a react app?
Also the back-end django app is uploaded on a heroku server and the front-end react app is using the urls of the app uploaded on heroku.
These two lines are nonsense:
data1 = json.dumps(request.POST)
data = json.loads(data1)
There would never be any point converting the form data dict to JSON and then straight back to Python.
However your issue is that you are not sending form data in the first place, but your are sending JSON. Replace those lines with:
data = json.loads(request.body)
If POST request is working fine with postman then there may be something wrong with the JSON format you are sending from reactjs.
console this.state and check if it is in correct JSON format.

Django form submit with ajax form.serialize()

views.py
def login(request):
password = request.POST.get('password')
mobile = request.POST.get('mobile')
user = authenticate(username=mobile, password=password)
if user is not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect("/owner/?own=" + str(user.id))
login.html
$('.login-form').on('submit', function(event) {
event.preventDefault();
var form = $(this);
$.ajax({
url: '/ajax/login/',
type: "POST",
data: form.serialize()
success: function(data) {
});
});
i'm getting error:
Method Not Allowed (POST): /
Method Not Allowed: /
[20/Oct/2018 04:41:30] "POST / HTTP/1.1" 405 0
You have a name conflict between your login function and the django built in login function, rename your function to something else like user_login.
I suppose you're missing csrf token? Try passing Django csrf token into your JQuery.

g-signin2 is not working with webapp2 (google app engine, users.get_current_user())

So, this is the sample python code:
import webapp2
from google.appengine.api import users
class HomePage(webapp2.RequestHandler):
def post(self):
#getting the email through a http call from the frontend
email = json.loads(self.request.body).get("email")
user = users.get_current_user()
print "incoming: ", email, user
The "email" prints correct signed-in user (which implies my g-signin2 is working) but "user" variable is null (which implies webapp2 is not understanding who's logged in)
Following is my HTML code:
<script src="https://apis.google.com/js/platform.js" async defer></script>
<meta name="google-signin-scope" content="profile email">
<meta name="google-signin-client_id"
content="<myclientid>.apps.googleusercontent.com">
<google-sign-in-button button-id="uniqueid" options="options"></google-sign-in-button>
Following is my angular directive (mostly irrelevent to this problem, but anyway just adding this to be sure):
app.controller('GoogleCtrl', ['$http', '$scope', function ($http, $scope) {
$scope.signOut = function () {
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('User signed out.');
});
};
$scope.options = {
'onsuccess': function (response) {
console.log(response);
var profile = response.getBasicProfile();
data = {
id: profile.getId(),
name: profile.getName(),
imageUrl: profile.getImageUrl(),
email: profile.getEmail()
}
$scope.commsApp(data)
}
}
//communication
$scope.commsApp = function (data) {
console.log("sendToApp; data: ", data);
$http({
method: 'POST',
url: '/',
data: data
})
.then(function successCallback(response) {
console.log("success. response: ", response);
},
function errorCallback(response) {
console.log("failure. response: ", response);
});
};
}]);
I'm able to pass on the profile information to my backend that is obtained when the user logs in through g-signin2 default button. But, when I use users.get_current_user(), I don't get any profile information. How do I get this working?
You're mixing 2 different authentication mechanisms:
the Users Python API
the Google Sign-In
The fact that a user signed in using google-signin on some application outside your GAE app and placed some maybe correct info (from that external app's point of view) into the request body doesn't mean that user is also signed in into your GAE app which uses users.get_current_user() from the Users API.
For users.get_current_user() to not return None the user must properly login at the URL obtained via users.create_login_url().

Categories

Resources