django-allauth test request as authenticated user - django

I have a new Django project (version 2.2), a custom user model and django-allauth to manage user registration (not via social, just with the email confirmation) and I'm trying to test some protected views.
In the setUp method of the test I create a new user and create a new EmailAddress (from allauth.account.models) with verified and primary set to True.
Next I try to login with: self.client.login(username=username, password=password)
and I get True so everything is working so far and the user is logged.
If I try to view anything that requires login, I get a 301 redirect to the login page.
Here's my code:
user creation in setUp
username = 'test#test.com'
password = 'testtesttest'
new_user = User.objects.create_user(
username=username,
email=username,
password=password,
)
new_user.save()
new_user.is_active = True
new_user.save()
new_email_address = EmailAddress(
user_id=new_user.id,
email=username,
verified=True,
primary=True,
)
new_email_address.save()
login and test logged in
logged_in = self.client.login(email=username, password=password)
self.assertTrue(logged_in) # and this works as expected
Now if I try to request a view that requires login:
response = self.client.get("/protected")
I get <HttpResponsePermanentRedirect status_code=301, "text/html; charset=utf-8", url="/protected/">
What am I missing or doing wrong?

The redirect you're showing actually shows you the url it's redirecting to: url="/protected/". So you're not redirected to the login page.
Note that a normal redirect would be 302 redirect (temporary), whereas here you see a permanent redirect, 301.
Either request the correct url (self.client.get('/protected/')) or follow through the redirects: self.client.get('/protected', follow=True). That way your response will be for the final page and you can test whether its contents are what you expect.

Related

how to create a custom session for log in user in Django

I am trying to login a user by sending a post request to an endpoint, the endpoint is returning status of 200 means the user information is true, but what i have been doing previously in django is simplify using authenticate method and passing user_phone and password later setting that resul to login(request, user_phone), now I dont know what to do here as here I am getting a response from that api which is just a user id, can we do something custom for this result.
user_is_authenticated = res['data']['user_id']
print('response',res['data']['user_id'] )
request.session['user_is_authenticated'] = True
print('response',request.session['user_is_authenticated'])
return render(request, "app/com-dashboard.html",{'user_is_authenticated':user_is_authenticated } )
here i am getting user_id, i just want to use user_is_authenticated just like we do in normal django app

Python Social Auth - User is authenticated with facebook but cannot access pages

I have an issue with Facebook authentication with Python Social Auth.
I have login with Facebook, Google and Twitter.
After login, I redirect the user to my dashboard at /user/dashboard with the use of login_redirect decorator. While it works fine with Google and Twitter, I am not able to redirect the user authenticated with Facebook.
#login_required
def home(request):
user = ""
if '_auth_user_id' in request.session:
user = AuthUser.objects.get(id=request.session['_auth_user_id'])
template = 'user/index.html'
return render(request, template, context)
In Settings.py
SOCIAL_AUTH_FACEBOOK_KEY = '******'
SOCIAL_AUTH_FACEBOOK_SECRET = '*******'
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email', 'public_profile', 'user_location']
SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
'locale': 'en_US',
'fields': 'id, name, email, age_range, about, picture, location'
}
SOCIAL_AUTH_FACEBOOK_API_VERSION = '2.10'
When I remove the login_required decorator, the user is redirected to the dashboard. But when the user tries to go to another page, there django says user is not authenticated. Is this an issue with the Facebook API or the application?
Thanks for any replies.
1) Check AUTHENTICATION_BACKENDS. Facebook authentication backend must be in this list.
2) Cleanup cookies and check that facebook user is_active on you site.
Here's a quick and dirty fix. I didn't look at all possible scenarios. This answer can be improved. First step is to get rid of the login required decorator from the redirect view. Then use the following code in the view
if request.user.is_anonymous():
# check if user logged in through facebook, csrf token will be validated by the middleware
if '_auth_user_id' in request.session:
auth_user_id = request.session['_auth_user_id']
user_obj = User.objects.filter(id=auth_user_id)
request.user = user_obj[0]
userProfile = model_to_dict(user_obj[0])
else:
# redirect user to login page
return HttpResponseRedirect('/login/')
You may have to update your app permission to provide the desired pieces of information(including email).
Go to https://developers.facebook.com/tools/explorer/, select your app and the permission you want to provide. Then generate a new test access token.

Django csrf fails after logout login new user

Even if I understand the problem, I'm not sure how to solve this. I have a django powered api that has an endpoint that lets the user change the email. If the logged user A enters a already existing email, it checks if the logged user A entered a password that corresponds to the already existing user B object (i.e he owns another, older account). If that is the case, I have to logout the actual user A and login again the already existing B account.
...
if User.objects.filter(email=email).exists():
# If the email already belongs to another account
user = authenticate(username=email, password=password)
if user is not None:
# The user is the owner of the existing account, he has the password
# Get already existing client object
client_existing_user_obj = Client.objects.get(user=user)
# get clients actual cart
actual_cart = client.cart
# update existing clients cart with newly created cart
client_existing_user_obj.cart = actual_cart
# logout user with the old email, login already existing user
logout(request)
login(request, user)
...
The endpoint works correctly, it returns 200. However, the next post & put requests answer 403 - "detail": "CSRF Failed: CSRF token missing or incorrect."
How can I solve this? Any advice will help.
Django rotates the CSRF token when a user logs in. This is a security measure.
You'll have to refresh the token after login (e.g by refreshing the page) before you submit more POST/PUT requests.

django tests response.request.user.is_authenticated() returning True after logout

I am trying to write some tests for the authentication part of my application and I encountered a problem with checking if the user is logged in or not. Here's the code:
client = Client()
# user signup form
response = client.post(signup_url, data={
'email': "lorem#ipsum.pl",
'password1': 'hunter2',
'password2': 'hunter2',
}, follow=True)
# checking if the user is logged in
with self.assertRaises(KeyError):
client.session['_auth_user_id']
self.assertEquals(len(mail.outbox), 1)
url = find_verification_url(mail.outbox[0].body)
response = client.get(url, follow=True)
self.assertEqual(200, response.status_code)
user = User.objects.get(email="lorem#ipsum.pl")
self.assertEqual(client.session['_auth_user_id'], user.pk)
# how to logout a user?
force_logout()
self.assertFalse(response.request.user.is_authenticated())
The user fills the form and clicks submit, then receives an email with a verification url. After he clicks the verification url in the email he's supposed to get directed to the site and authenticated. My questions is, what is a good way to find out if the user is authenticated or not? What is a preferred way to log out a user in this situation? I want to check that if the user is logged out and clicks the link the verification link second time it doesn't work. I tried some things like:
client.logout()
But unfortunately it seems to work once every two times even when I remove this line.
Thanks for any help!
Ok so the problem was that the authentication system was using a timestamp function to know if a url was expired or not. When run in a test the verification url was not expired when it should be. The login request after the logout was too fast and the system was thinking that the verification url was still valid and the user got authenticated. And that's why user.is_authenticated() was returning True all the time.

Django - How to remove the cached user data of the last session in Python Social Auth?

I'm making a sample login app with Python Social Auth.
My app provides the user the chance to login with facebook or twitter.
Let's say the name of my facebook account is boel.facebook and the one for twitter
is boel.twitter.
This is a fragment of my papeline.
def get_profile_picture(
strategy,
user,
response,
details,
is_new=False,
*args,
**kwargs
):
img_url = None
if strategy.backend.name == 'facebook':
img_url = 'http://graph.facebook.com/%s/picture?type=large' \
% response['id']
elif strategy.backend.name == 'twitter':
img_url = response.get('profile_image_url', '').replace('_normal', '')
print('THE USER IS: %s'%(user.username))
###
If the user makes login with facebook, the console prints
"THE USER IS: boel.facebook"
and the app redirects to the logged page where I have a link for making logout,
which calls the following function in views.py:
def logout(request):
auth_logout(request)
#redirect to login page.
At this point the user is back to the login page. Until here, everything is OK.
Now, if the user tries to login with twitter this time, Python Social Auth
redirects to the twitter login and after the user successfully authenticated,
the pipeline is called but the console prints:
"THE USER IS boel.facebook" again.
So, what am I doing wrong here?
Since the user is authenticated with twitter this time, the console had to print:
"THE USER IS boel.twitter".
Please help.