apache authentication against django application - python

I have the following problem:
I wrote an application in Django, basically it’s some kind of management platform for my choir. Now we have some files that we want to provide to our members, but only to them (i.e. registered users). Additionally, there are some files that should only be accessible to the management. Ideally, I want to be able to define in the database who can access which files.
Here is some information about the environment:
Server OS Debian 8.7
Python version 2.7
Django version 1.10
Mod_wsgi version 4.3
What have I tried so far?
Django documentation provides a very, very small example of how to authenticate against the database.
The part where I only validate whether the user is a valid user works. Although it kind of sucks, since the users have to login again every time they access a file.
The part where I validate whether the user is a group doesn't work at all. Apache says:
Unknown Authz provider: group
Then I started to look up this problem, which led me here. When I use the option wsgi-group the apache configuration doesn't cause any problems, but it apparently doesn't validate whether the user is in the specified group either. (I tried to access the file with a user who is not in the specified group and succeeded...)
Now here are some questions I have to this problem:
Has anyone else experienced these problems with the Require group/Require wsgi-group option and has found a solution?
Is there a possibility to "link" the session of the website with the session of the apache file access? As I already mentioned, it is not very user-friendly if the users have to login again every time they want to access a file..
Is there a possibility to write a custom authentication function? Technically, looking at an example implementation for the authentication method check_password (here "auth.wsgi"), I could overwrite this function, provided that the environ variable contains the URL that the user wants to access. (does it?)
This would probably be the most dynamic solution, but I don't quite know if this is possible. The basic idea ist that I render a button in the view for each downloadable file, that sends a POST to the server. The server checks whether the session user has the rights to access this file, and, if true, returns the file. This would mean that the file can only be accessed by the application and not through the apache. Is this possible?
I hope someone can help me, thank you in advance anyways =)
Edit: I did some research and found an answer for my last question here (Having Django serve downloadable files). With the mod_xsendfile this is apparently manageable pretty easily. That leaves just 3 more questions ;)

I have also used X-Send for various purposes within my Django App (usually to serve up files stored in FileFields) but for hosting a suite of static pages such as sphinx-generated pages and supporting media, proxying via X-Send has lead me into more problems than solutions.
As I was researching my own question I discovered yours and realized that mine is the solution to your question #1 and #2: Use mod_wsgi's WSGIAccessScript config with the allow_access(environ, host) function to instantiate a Django WSGI Request which can be programatically distilled to a boolean using whatever business logic you require. I hope someone else can answer my more specific concerns about the approach, but it is functional.
Your question #3 suggests I point you towards Django's Custom Authentication Backend documentation. I have written a custom backend that uses email addresses to authenticate a user rather than requiring users to remember an arbitrary username.
#Django Imports
from django.conf import settings
from django.contrib.auth.models import User
class EmailAuthBackend(object):
"""
Email Authentication Backend
Allows a user to sign in using an email/password pair rather than
a username/password pair.
"""
def authenticate(self, username=None, password=None):
""" Authenticate a user based on email address as the user name. """
try:
user = User.objects.get(email__iexact=username)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
""" Get a User object from the user_id. """
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None

Related

Django: Intervention when raising errors when creating User via social authentication

I'm setting up social authentication with the package social-auth-app-django. I have the below ValueError raised when attempting to create a user when an email isn't supplied.
users.py
if not email:
message = "Ooops, it doesn\'t look like an email was specified. If you are signing in via one of your social media account, please ensure there is an email address associated to your account."
raise ValueError(message)
It wasn't really necessary originally as I would handle the form validation on the front end with standard form validation. However, when integrating social sign-ins this causes an issue. In development this is great - but essentially at this stage I would like to fling the error back to an errors template which says that they must supply an email address. I believe on platforms, such as Twitter, a user can initially register without an email address associated to the account. That's where I spotted this conflict. Essentially, social-auth-app-django isn't throwing an error before this - so how at this point, do I send the user back to a specified template which I can build to handle such errors by passing them back via the context?
Looking and looking through the documentation, I can't see anything I would be confident in running with...any advise would be greatly appreciated!
The python-social-auth module supports a pipeline - so defining a method in the end of your SOCIAL_AUTH_PIPELINE in settings.py and then implementing it in pipeline.py would give you a way to define the desired behavior in case, when your users have no email associated with their social users:
SOCIAL_AUTH_PIPELINE = (
# any other pipeline handlers ...
'custom.signup.pipeline.prevent_without_email'
)
Then in your custom/signup/pipeline.py you'll need to implement the actual partial for prevent_without_email - You can see it here in more detail http://python-social-auth-docs.readthedocs.io/en/latest/pipeline.html
If you need a specific handler, you can use Django signals - create a signal in signals.py, emit it in pipeline.py and let the handler in callbacks.py to handle it, when an email is not specified.

Flask-restful API user accounts. Get full data and access to modify it if owner of account, get partial data otherwise

this is my first attempt to create a RESTful app using Flask framework. This is an API for cooking recipes. I already have basic functionality but I have encountered a problem with user accounts and content based on "logged in" user (username from authorization).
I run through many tutorials and documentations, but I have not found a solution I'm looking for. Only user/role based authentication to give or deny access to specified resource.
Simply: Everyone registered can see all users and their data, but only owner of the account can access full data and modify/delete it.
I've decided to use #auth.login_required decorator to check if user is registered and then in other methods (GET, POST etc.) use my own function to compare username from URL with username from auth header:
def is_owner(username):
if username == request.authorization.username:
return True
else:
return False
but I don't think this is a proper way of doing this. In POST, PUT, DELETE methods this is quite simple, because I either give or deny access, but in GET methods I want to return only part of information, so e.g. only username to guests, and full data containing email etc. for owner of the account. Same applies to other GET methods (return all recipes to owner or only those marked as public). This generates a problem with response because I would have to create new fields for each type of response in order to use marshal
The whole source code of this application is on my github.
This is mostly related question I've found, but I wonder if there are better ways.
There are for sure many bugs and strange ways in which I do some things as this is my first try. If you have some comments not regarding this particular question please let me know in comments or on my github page.

Implementing social login in Flask

Looking to implement social authentication in our application with LinkedIn, Google, Facebook. I'm currently using flask-security to help manage users/roles in our application. I'm looking for some guidance on best practices with Flask/Flask-Security and Social Authentication.
I've seen the flask-social plugin, but I'd like to have the option of local form-based login, too.
So far, I'm planning on writing a new login view implementation for flask-security that can determine whether I'm using a social site (via passing a query parameter when user clicks on "login with XYZ") for the login. After social authentication occurs, I was planning on running the regular flask-security login to set all the appropriate session tokens and user and roles so the #login_required decorator will continue to work.
I didn't really see any hooks for overriding the login view function in flask-security, so I'm planning on either 1) copying the existing implementation into my own app or 2) calling flask_security_views::login.
However, I'm wondering if there's some of this that's already been implemented somewhere, or a better start. It seems like I'm really going to be cutting up a lot of existing code.
Thanks
Mark Hildreth is correct.
flask-social allows you to log in via a form (username/password) or via social.
So you can use it in conjunction with flask-security, flask-login, or whatever password-based authentication you want. I have used flask-social in conjunction with flask-security and can confirm they work quite well together.
flask-social links each User object to zero or more additional social accounts, which are stored in a separate table/datastore. Thus, it does not replace the existing password infrastructure...it just augments the User model and adds additional social methods to also allow for the user to log in alternatively via social accounts.

Role-based authorization mechanism for a GAE app

I'm looking for a role-based framework/module/package for an app written in Python (2.7) running on Google App Engine.
With role-based I mean a mechanism that would allow me to check (during a request processing most of the time) whether a certain user is able to perform a specific action.
A couple use cases:
user A should be able to see and modify own profile, whereas user B should only be able to see user A profile.
user with an "admin" role should be able to see all registered users, whereas user A and user B should only be able to see users with a public profile (e.g. users with user.public property set to True)
etc.
I'm imagining something like
user_a.is_able_to('read', user_b) # -> True of False
or
user_a.authorize('update', user_b) # raises an exception if 'not allowed to'
So far I've only seen acl.py from tipfy. Looks quite simple and pretty much close to what I'm looking for. I'm wondering whether there's something similar to that acl.py, preferably implemented using NDB.
Web2py contains role based access control which I believe works on GAE. This is documented here:
http://web2py.com/books/default/chapter/29/9
You may be able to fork the auth module and mod it for your purposes. I know people have done this with other parts of web2py such as the DAL.
Turbogears and Web2py frameworks have the role based access control you can integrate one of them on GAE Python version.

How to manage authentication across handler classes in google app engine /w python

Taking into account that I barely know python and am simply following the "hello-world" example here: http://code.google.com/appengine/docs/python/gettingstarted/
I'm unclear as to how I would: use a "MainHandler" class mapped to '/' as a welcome page, ask the user to login and then only allow logged-in users to access a "EditorHandler" class mapped to '/editor'
You've asked a very broad question, and provided no details about what (if any) framework you're planning to use to implement your app. I guess you are probably using webapp?
The basic idea would be to create a login url that you redirect the user to, or you provide to them. If you want them redirected to an edit page on your app, you can specify a dest_url when calling create_login_url:
users.create_login_url(dest_url='/edit')
Within your code you can secure your edit handler easily in app.yaml or with the '#login_required' decorator, depending on how you've setup your app.
This seems to work: http://appengine-cookbook.appspot.com/recipe/login-decorator
Although I dont understand the magic behind most of it, it's probably due to my lack of python skills.
Some comments on that article also point to more "native" solutions:
http://code.google.com/appengine/docs/python/tools/webapp/utilmodule.html

Categories