Get user object using userid in django - python

Hello i am new to django,
i am creating an authentication system using django.
Once a user is logged in i am storing the value in a session.
user = authenticate(username=username, password=password)
request.session['mid'] = user.id
and when i refresh i can receive the session id
uid = request.session['mid']
But i am not sure how to get the userdatas from the user id. can any one tell me how can get the user object using the user id.

Use simple .get() query.
try:
uid = request.session['mid']
userobj = User.objects.get(id=uid)
except User.DoesNotExist:
#handle case when user with that id does not exist
...

Of course, you can store the user id in request.session, and query the id
with django ORM manually.
But after installing the SessionMiddleware and AuthenticationMiddleware middlewares, on a higher level, Django can hook this authentication framework into its system of request objects. I believe most django projects will use the code below to get authenticated user from web requests.
if request.user.is_authenticated():
user = request.user

Related

Django not logging in properly when custom backend and models are used

I'm trying to implement a custom authentication backend in Django but its behaving in a very strange way. The custom backend authenticate against a different model from the usual Django User model an upon successfully verifying the provided credentials the backend get or create our usual Django User instance which it returns. Login nevertheless doesn't work.
From the documentation I learnt that I just needed to inherit the django.contrib.auth.backends.BaseBackend and override the authenticate() method which I did. As I've mentioned the custom authenticate() method basically verifies a set of credentials (username and password) against ones stored in the database (custom model, not django.contrib.auth.models.User) which if matched it would get or create an instance of django.contrib.auth.models.User via a proxy model which I named Profile; basically the Profile model has a reference of both django.contrib.auth.models.User and my custom model. When logging in though I keep redirected to the login page (It's like Django logs me in but doesn't set something somewhere such that when I try accessing a protected resource I'm redirected back to login). Also when I login which a django.contrib.auth.models.User object it works just fine and I can access the protected pages. Following are the reasons I opted for this authentication approach.
I'm working with an existing database that has it's own User tables with very different schema than what Django provides.(Actually the only fields in this system User table similar to Django's are username, and password)
I utilized Django's inspectb management command to recreate the models of which I'm under strict instructions to leave unmanaged, you know, manage=False in the model's meta class. Basically I can't inherit Django's AbstractUser as it would require new fields to be added.
Thus the best approach I could think of was to use a proxy model that would link both django.contrib.auth.models.User and my custom unmanaged models with a custom Authentication Backend.
I've tried watching for certain variables such as the request.session dictionary and request.user all which are set but still can't login successfully. Also when I use credentials that are not in either of the two models I get a Invalid Credentials message in the login page (desirable behavior).
Actually, my custom authenticate() method works fine and returns a valid user, the issue I think lies in django.contrib.auth.login. What could be the problem?
Here is the my authenticate method
def authenticate(self, request, username=None, password=None):
try:
c_user = CustomUser.objects.get(username=username)
except CustomUser.DoesNotExist:
return None
#pwd_valid = check_password(password, user.password)
if not c_user.password==password:
return None
#Get and return the django user object
try:
profile = Profile.objects.get(custom_user=c_user)
user = profile.user
#Create user if profile has none
if not user:
user = User.objects.create(
username=''.join(secrets.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(24))
)
profile.user = user
profile.save()
#Create new profile if none exists
except Profile.DoesNotExist:
#Create new user for the profile
user = User.objects.create(
username=''.join(secrets.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(24))
)
Profile.objects.create(
user = user,
custom_user = c_user
)
return user
Here is how I added the custom backend to settings.py
AUTHENTICATION_BACKENDS = [
'Authentication.custom.CustomAuth',
'django.contrib.auth.backends.ModelBackend'
]
Can't believe I'm answering my own question. After much debugging and reading documentation I realized I didn't override get_user method of the django.contrib.auth.backends.BaseBackend thus the default one which returns None was always called. I implemented it and it worked like a charm.

How to create a new user in Django using LDAP?

I'm using Django to create a REST API with LDAP. One of the endpoints gets a username (this is not the same username of the logged in user through IsAuthenticated). I want to check if that username exists in the system, even if he never logged-in. My current code was:
try:
user = User.objects.get(username=request.data['username'])
except:
return Response(data={"error": "User does not exist"}, status=status.HTTP_400_BAD_REQUEST)
This of course does not work because the database contains users that have logged in at least once. How can I create the user if he does not exist? I know I can use User.objects.create but I want it to fetch the data from LDAP and not just to pass it the username.
The logic that I'm after:
Check if the username does not belong to any user via LDAP. If so, return error message.
Otherwise, create/populate the user and do other actions (based on the purpose of the endpoint).
I'm using django_auth_ldap.

Is it possible to forge HttpRequest attributes for a Django server

I am writing a web app using Django. I am trying to allow a user to see its profile and only his own.
if(not request.user.id == request.GET.get('user_id', '')):
raise PermissionDenied
My question is: is it safe to check this way or is it possible for a smart kid to somehow alter the value in request.user.id to match the user_id of anyone?
The user must be logged in before accessing this page using this:
user = LDAPBackend().authenticate(username=username, password=password)
if(user is not None):
login(request, user)
Yes it should be safe.
request.user get's only populated when authentication with session cookies. Unless and until someone steals the cookie or token it should be no issue.
One thing i don't understand is why do you need user_id parameter here to be explicitly passed.
if you are putting logged in compulsory to view the page. there are two way i can see this.
/profile
Directly get user profile corresponding to the request.user
/<username>
Query the profile corresponding to the username and compare it with request.user.id
request.user is set using AuthenticationMiddleware for each request:
Adds the user attribute, representing the currently-logged-in user, to every incoming HttpRequest object.
If a user is not logged in then request.user is set to Anonymous User. Have a look at Authentication in Web requests.
So, I am not sure how would a smart kid alter the id of the logged-in user.
Mostly, there is a one-to-one relation between the user and its profile. If that's the case you can modify the queryset to get the profile for request.user directly.
request.user is already an object about the current user who send the request to get the page. You can use login_required or to only allow user login to access (2 solutions : decorator or Mixin).
And then you can use your condition to load the page in the function. Example:
=> url.py:
url(r'^profile/$', login_required(app.views.profile), name='profile'),
=> views.py :
def profile(request):
try:
myProfile = User.objects.get(username=request.user.username)
except ObjectDoesNotExist:
return render(request, "error.html", {'message' : 'No Profile Found'})
return render(request, "app/profile.html",
{'myProfile': myProfile})
Like this you can only display YOUR profile (user who send the request) AND you need to be logged.
EDIT: if you don't want "try and catch" you can use get_object_or_404(User, username=request.user.username)

How to update a user's `extra_data` after they have been associated with account?

I've successfully managed to use django-socialauth to associate an account (in this case, an instagram account) with an existing user account. I've also set up my pipeline to collect additional user details:
def update_social_auth(backend, details, response, social_user, uid, user,
*args, **kwargs):
if getattr(backend, 'name', None) in ('instagram', 'tumblr'):
social_user.extra_data['username'] = details.get('username')
social_user.save()
This works great when an account is associated for the first time. However, if the account has already been associated, the username field will not be present in extra_data.
How can I update a user's extra_data after the association has already been made? Is there a way using django-socialauth to do this without disconnecting and reconnecting, or using the account's (e.g Instagram's) API?
If it helps, this is my pipeline at the moment:
SOCIAL_AUTH_PIPELINE = (
'social_auth.backends.pipeline.social.social_auth_user',
'social_auth.backends.pipeline.social.associate_user',
'social_auth.backends.pipeline.social.load_extra_data',
'social_auth.backends.pipeline.user.update_user_details',
'apps.utils.social.utils.update_social_auth'
)
Here is a snippet of code I use to add 'admin' and 'staff' options to an existing Django user; I don't know about django-socialauth or the extra_data field, but I'm guessing something like this might be applicable:
:
userqueryset = User.objects.filter(username=user_name)
if not userqueryset:
print("User %s does not exist"%user_name, file=sys.stderr)
return am_errors.AM_USERNOTEXISTS
# Have all the details - now update the user in the Django user database
# see:
# https://docs.djangoproject.com/en/1.7/ref/contrib/auth/#django.contrib.auth.models.User
# https://docs.djangoproject.c om/en/1.7/ref/contrib/auth/#manager-methods
user = userqueryset[0]
user.is_staff = True
user.is_superuser = True
user.save()
:
FWIW, my app is using 3rd party authentication (specifically atm OpenId Connect via Google+), so I think there's some common goal here. In my case I want to be able to add Django admin privileges to a user that has already been created.
The full module containing the above code is at github.com/gklyne/annalist/blob/develop/src/annalist_root/annalist_manager/am_createuser.py#L231

How to get the the User ID from an email in GAE

I'm working on a small app that will allow the user to login to the App, allow the app OAuth access to a service, then interact with the service using the app via email.
I've successfully enabled Oauth using gdata and gdata.gauth and can store/recover the Oauth token and user_id easily when the user is logged in.
However, when receiving an email, I try to get the user_id by creating a users.User(email="senders.email#gmail.com") but end up getting a None value for the user_id.
ie:
when logged in:
current_user = users.get_current_user()
current_user.user_id() #this is a valid id when the user is logged in
when receiving an email (using the mail handler):
current_user = users.User(email="sender.email#gmail.com")
current_user.user_id() #this returns None
Any hints on how to make this work?
Reading http://code.google.com/appengine/docs/python/users/userclass.html#User
Under the method call user_id, it is noted that if you create the User object yourself, the user_id field will return None.

Categories