I have a Django application (mainly a rest API) with a completely custom User model (not inhered from Django). My authentication is based on JWT tokens.
I would like to make sure a user cannot access to data of another user. I have checked the django-guardian and django-rules. It provides stuff to call a has_perm function. However, in the case the developer does not perform the check and makes a mistake (for example hardcoding the user id in a query), a user might be able to access someone else data
Is there any way to enforce some kind of rule at the ORM level?
Related
I know that one can set up authentication with the built in django login(request, user), request.is_authenticated when the user acquires the sessionid cookie, and authenticate(request, username="foo", password="bar").
However, underneath this interface, django creates a User object in the database. I am authenticating using other means, namely LDAP. I can opt for just passing the username and password for LDAP every single time, but having a sessionid token would be ideal.
Is there any way to use the same login(), request.is_authenticated, authenticate() API but without using the User model underneath? Another alternative is fine as well. The one restriction that I have is that I do not want to use another library.
Thanks!
As far as I know, its not possible to use djangos authentication/autorization framework without the User model.
In the part where the docs talk about customizing authentication, it is always centered around the User model (even if it is your custom user model).
That being said, you could look into something really hackish: creating your custom user model that is not stored in the database.
For that you'll probably need custom fields and managers that prevent database calls while still making certain fields available in the model (like email and username). I never tried it, but it should be possible by overriding djangos default behavior in the right places.
But all that effort is probably not worth the trouble. Just write your own authentication backend that automatically creates an User instance on successful authentication against your LDAP source, so you can "harness the full potential of the django User model".
On the client side I use the iOS SDK for Facebook to login and I get the Facebook ID and the access token.
Now on the Django side of things I would like to create a user with Facebook ID as the primary identifier and other fields like access token, first name, last name etc (the last two of which I will retrieve from the Graph API on the server side).
I know that I have to create a custom user model.
If you wish to store information related to User, you can use a one-to-one relationship to a model containing the fields for additional information. This one-to-one model is often called a profile model, as it might store non-auth related information about a site user.
This will not be enough as I will be using the Facebook ID and the access token for authentication.
This leaves me with two options: I can substitute a custom user model like so:
AUTH_USER_MODEL = 'myapp.MyUser'
Or I can subclass AbstractUser:
If you’re entirely happy with Django’s User model and you just want to
add some additional profile information, you can simply subclass
django.contrib.auth.models.AbstractUser and add your custom profile
fields.
But that doesn't sound quite right either. Also this design tip has confused me a little more.
Model design considerations
Think carefully before handling information not directly related to authentication in your custom User Model.It may be better to store app-specific user information in a model that has a relation with the User model.
What is the best way to implement what I am trying to do?
Just a side note: The problem of a custom user is that it is often the case that other apps (and yes, you will use them) don't interact correctly with it due to the assumptions they make on the base model for auth.
This will not be enough as I will be using the Facebook ID and the access token for authentication.
I'm not sure you really need a custom user. For instance, I'm using open id for authentication and there is no problem in using the default user: there is just another model with a OneToOne relationship to the default user.
The main concern you should have for a Facebook ID for authentication (and authentication in general) is to have a custom authentication Backend with its own specific facebook authentication.
Internally, authenticate() runs through all installed backends (settings.AUTHENTICATION_BACKENDS) and tries to authenticate the user with one of those.
You can search some of the existing implementations e.g. in Django packages for facebook authentication.
If your users should be enabled to login/register with username, mail and password -> use a OneToOne relationship to django's usermodel to store facebook credentials.
If your usermodel entirely depends on facebook data and you don't want your users to login with username/pass -> substitute the usermodel with AUTH_USER_MODEL = 'myapp.MyUser'.
You might also want to take a look at django-allauth which solves much of your problems in a sweet little package.
I've recently started using Pushover.net, I've done some searching and can't find any examples of it being integrated with a django project.
Since i can't find any examples I've decided it would be fun to try myself. What I'm interested in is how you would suggest I do it. I want the actual pushover part as decoupled a possible, hence doing it asas an app.
What I'm not entirely sure on how to approach is the user authorization. The idea being a user enters their pushover user key and its saved in a user profile model using django's AUTH_PROFILE_MODULE with some functions such as has_pushover but obviously I'd like some security so the user keys aren't stored in plaintext. What do people suggest for this?
Is there some inbuilt django security I can use?
In the past when I've needed to encrypt Django fields I used the encrypted fields available in django-fields. You could use one of these on your UserProfile model and define a has_pushover() method on the model which basically returns whether the pushover token field is None or not.
I'm guessing because you're talking about storing each user's Pushover token you are wanting to build an app for pushing arbitrary notifications to your website's users? This is in contrast to having the website just push notifications to yourself for site events.
How do you ensure that a User can only edit objects they've created? What's the best way to set this up?
I'm using django-rest-framework and wondering if there's a way I can restrict users from viewing/ editing objects they don't 'own'.
class Video(models.Model):
owner = models.ForeignKey(User)
...
So User 'x' should only be able to edit videos in their owner_set.
Presumably you have sessions and the auth model turned on.
You must be sure that all views (REST and non-REST) require authentication.
For non-REST, it's easy. You simply use a basic #login-required decorator everywhere.
For the Django-REST Framework, read this: http://django-rest-framework.org/library/authentication.html#module-authentication.
You have to use the authentication mixin to be sure that authentication actually happened.
The framework supports BASIC Authentication, which requires an SSL connection to be secure. It's not too difficult to implement DIGEST authentication, which doesn't require SSL.
Avoid sessions. It violates a principle of REST to login and logout. The framework supports sessions, but it's less than ideal.
Once you have all requests authenticated, you'll know the user.
If you know the user, then user.video_set works perfectly. You can also use Video.objects.filter(...) to be sure that you're querying the user, but it's easier to confirm the code is correct if you work with user.video_set.get(...) or user.video_set.filter() or whatever.
All the relevant authorization checking is done in Views. You're providing Views for your ModelResources.
These are "class-based views". Documentation is here: https://docs.djangoproject.com/en/dev/topics/class-based-views/#viewing-subsets-of-objects
The trick is to pick all the right mixing and serializers.
For example, you can mixing get processing this way:
http://django-rest-framework.org/howto/mixin.html
You'll implement the filter in the get method
I have developed an app for school management. Teachers and others roles have an account (django user) to control student attendance, Behaviors issues, etc.
Student is a model itself. Teacher is a User proxy.
At this moment I'm ready to extend the app to allow parents access to children information (is cruel, but for the sake of students ;)
I'm evaluating this alternatives:
Make a simple php app only for parent access (with dedicated db user
and views). It seems secure but I don't like php.
Add a password field to Student model and build my owner authentication system. I
don't like to have a 'django authenticated student'.
Integrating Student authentication with actual auth schema. I don't like this for
security reason, this means to check all views security, and this mix teachers and students.
Create a new django application only for students (and parents) with two databases, the 'school' database and a new one with auth for students
What is for you the best way to authenticate parents before to see children information?
Any suggestions are wellcome. Thanks a lot.
Ah! I think that is easy that parents forgot passwords.
School has over 800 students, app store more than 1milion of presence cheks for year, lot of Parents interviews, ...
Django contrib.auth models incorporate groups and permissions in addition to user accounts. In fact regular django users and django admin users share the same model only with different permissions.
Considering, the default authentication model (from a security standpoint) is already shared with much bigger consequences in case of a breach, I don't see a reason why you shouldn't have students authenticate with the same model and just assign them into a separate group and manage their permissions. Your security will not be worse or better from what it already is.
As far as development side goes, all you have to do is simply use decorators on the view handlers which are Teachers/Parents only to limit student access to them.
See: Permissions decorator
If for whatever reason this is unacceptible (although I cannot surmise a reason from what you said), you will have to do either:
Write your own middleware that injects itself into contrib.auth (reinvent the wheel)
Use an external system to verify permissions (completely orthogonal to Django's approach and will actually complicate your system much more than to use integrated contrib.auth)
Additional down side to doing your own authentication system is that you now have to worry about all kind of security issues that Django solves for you (like CSRF protection, SQL injection/escaping and many others). Not to mention bugs that can creep in vs. using tested and proven code/model provided by contrib.auth.