How to get user name after authentication? - django

I built a website using Django and Apache. I have Apache LDAP authentication. How do I get the username after the user authenticate to the website? I want to get the username and represents it.

So you're using Apache LDAP Authentication. If you use mod_auth_ldap, see the docs here http://httpd.apache.org/docs/2.0/mod/mod_auth_ldap.html#frontpage. If you use
mod_authnz_ldap see the docs here https://httpd.apache.org/docs/2.4/mod/mod_authnz_ldap.html#exposed.
What the docs tell is that, when the user is authenticated Apache sets environment variable, that can be accessed from CGI script. Variable name varies depending on the version you use. Though Python uses WSGI, you should still try to get the variable as it's environment variable and should be accessible anyway.
In python to get access to environment variable:
import os
username=os.getenv["REMOTE_USER"] #will return variable value or None
if username:
pass
#process username here
See docs on this function here: https://docs.python.org/3.5/library/os.html#os.getenv
You can try to use this directly in your Python code where you expect the username. Or better use this code in wsgi.py in your Django project and if username is available add special header with its value, so that it will be available inside Django in request passed to Django views. But remember to strip that header before adding it, so if a malicious user forges the header it doesn't affect your app. For more information on this see https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/modwsgi/ and https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/apache-auth/.
Edit: Btw, there's a "How-to" for REMOTE_USER: https://docs.djangoproject.com/en/1.9/howto/auth-remote-user/
Edit: If you don't have any requirements for performing authentication with Apache, you might want to perform authentication in Django app directly, see: https://pythonhosted.org/django-auth-ldap/ and in example https://djangosnippets.org/snippets/901/.

Related

How do I protect a password stored on server?

So, I set up a Django project and I'm done with it. Anyway, there's a function in the views.py script that is meant to send an email. I'm using the smtplib library and of course I need to login to send the email through my email address, so in that script my email and my password are written.
I'll publish this project (hosted by Heroku) so I'm worring about the password protection.
What do you think? Is the password protected or do I need to protect it in some way? I don't think it could be possible to access the views.py script but I'm not sure.
For anything like this, you should avoid putting the password in the code at all. Rather, get it from an environment variable, which you can then set via the command line with heroku config:set. See the Heroku docs.
You can and should use .env files for this. On heroku you have the option to add environment variables without .env files.
EDIT:
A bit of info about .env files: they are used to load environment variables from a file (the .env file). You usually don't commit them to SVN, but an "example" of what should go into the file, which is usually named .env.example. Depending on what's your setup for running the app there are different ways of supplying those environment variables, but you always access them in the same way in your code.

how can i check that a admin user is logged into django website or not into NGINX

I want to see that admin user is logged in or not into nginx.conf file .
I need this for my specific requirement.
My Try :
I tried to fetch COOKIES into nginx.conf file.
but when admin is logged out so cookies are changed so i am not able figure out that if a admin is logged in or not.
As far as I know this is not possible.
Django uses encrypted cookies by default and stores all data in the session table in the DB (also encrypted). You could check if the user has a cookie set in nginx but you won't be able to verify if that cookie value actually means "Admin" or "random other cookie value".
Also unless you're using custom nginx modules to check the contents of the cookie you run the risk of someone managing to trick nginx into thinking the user is an admin when that is not the case.
I'm not sure what the use case is here but you could try doing something with the django middleware or looking for third party plugins instead of using nginx.
If you want to limit file access to a specific file, e.g. admin-only images/javascript/data files or such you could try the HttpAccessKeyModule for Nginx and just generate a custom 'url' for your admin to access them.
You can also try looking into: http://nginx.org/en/docs/http/ngx_http_auth_request_module.html and see about delegating the check to some part of Django which just returns Yes or No to nginx.
There might be another nginx plugin somewhere which you can add/enable for an admin user from within django. But this requires you to think the other way around. With django telling nginx the user is an admin. Instead of nginx finding it out itself.
Hope this helps you in some way.

Setting up LDAP for Django authentication

I am working on a Django-based intranet app which needs users to authenticate against Active Directory. I've found django-auth-ldap, but I still have absolutely no idea what to do in order to setup a local LDAP server which I could develop against.
I installed AD LDS, but it needed a domain controller, and some SO answers that I read told me that I can't setup that on Windows 7. So I decided to try OpenLDAP instead, and it looks like it's working, but the tutorials I read weren't particularly clear on how the hell do I add data to it?
Would anyone please explain to me what steps do I need to take in order to add and successfully authenticate a Django user profile against a locally running LDAP service, be it OpenLDAP or Active Directory (I'll need to know how to successfully set up the later, if that's at all possible)?
You may have already solved this by now but just in case:
You need to setup your LDAP repository (done).
You need to create some user objects which can bind. This is accomplished by using an LDIF file or a similar method. A very useful tool for visualising your LDAP db is 'Apache Directory Studio'. An example of how an ldif may appear:
dn:cn=myuser,cn=localhost
changetype: modify
add: cn=myuser
userPassword: password01
It will vary depending on your schema. I highly recommend you read the Django docs for implementation specific to you: https://pythonhosted.org/django-auth-ldap/
This is a good example (from the docs):
import ldap
from django_auth_ldap.config import LDAPSearch
AUTH_LDAP_BIND_DN = ""
AUTH_LDAP_BIND_PASSWORD = ""
AUTH_LDAP_USER_SEARCH = LDAPSearch("ou=users,dc=example,dc=com",
ldap.SCOPE_SUBTREE, "(uid=%(user)s)")
but assuming you had added a user via ldif to "cn=localhost" then thats the dn you'd use in the search field. As the docs note, you can search the whole directory if you prefer.
If its not clear what is happening:
Import Ldap Module
Import LDAPSEARCH function? from the django module
Set a blank bind DN (this is like a fully qualified username. e.g. uid=myuser,dc=com)
Set a blank bind password
Perform the search. Format like so: ("base",scope,searchfilter)
You can test using the standard ldap module in python:
import ldap
ld = ldap.initialize("ldaps://acme.com:636")
ld.bind_s("userDN","Password")
ld.search_s("cn=acme.com",ldap.SCOPE_SUBTREE,"uid=myuser")
Not really important, but "ldap.SCOPE_SUBTREE", "ldap.SCOPE_BASE" etc are just integers. So you can pass in 0, 1, 2 instead.
Good luck, even if you solved this long ago.

How do you Require Login for Media Files in Django

I'm serving "sensitive" information in downloadable PDF's and Spreadsheets within a user registration section of a site.
Is there a way to allow the django authentication to secure this media without serving it (and not have to manually login using basic auth)?
I'm guessing theres (fingers crossed) not a way to do it with the psuedo code below, but it helps better illustrate the end goal.
#urls.py
(r'^protected_media/(?P<filename>.*)$', 'protected_media')
#views.py
from django.contrib.auth.decorators import login_required
#login_required
def protected_media(request, filename):
# #login_required bounces you out to the login url
# if logged in, serve "filename" from Apache
It seems to me that the method you outlined in your code should work. It's really no different than any other protected resource: your views can serve files from disks, records from databases, rendered templates or anything. Just as the login_required decorator prevents unauthorized access to other views, it will prevent such access to your view serving protected media.
Am I missing something from your question here? Please clarify if that's the case.
EDIT: With regard to the django doc link in your comment: that's the method for simply serving any request file from a particular directory. So, in that example URLS like /site_media/foo.jpg, /site_media/somefolder/bar.jpg will automatically look for files foo.jpg and somefolder/bar.jpg under document_root. Basically, every thing under document_root will be publicly available. That's obviously insecure. So you avoid that with your method.
It's also considered inefficient because django is just adding a lot of unnecessary overhead when all you need is something like Apache to take a URL request and map it to a file on the hard drive. (You don't need django sessions, request processing, etc.)
In your case, this may not be such a big concern. First, you've secured the view. Second, it depends on your usage patterns. How many requests do you anticipate for these files? You're only using django for authentication -- does that justify other overhead? If not, you can look into serving those files with Apache and using an authentication provider. For more on this, see the mod_wsgi documentation:
http://code.google.com/p/modwsgi/wiki/AccessControlMechanisms
see the section "Apache Authentication Provider" and search for django
There are similar mechanisms available under mod_python I believe. (Update: just noticed the other answer. Please see Andre's answer for the mod_python method.)
EDIT 2: With regard to the code for serving a file, please see this snippet:
http://www.djangosnippets.org/snippets/365/
The send_file method uses a FileWrapper which is good for sending large static files back (it doesn't read the entire file into memory). You would need to change the content_type depending on the type of file you're sending (pdf, jpg, etc).
Read this Django ticket for more info. Start at the bottom to save yourself some time. Looks like it just missed getting into Django 1.2, and I assume also isn't in 1.3.
For Nginx, I found this Django snippet that takes advantage of the X-Accel-Redirect header, but haven't tried it yet.
If I understand your question correctly you want to restrict access to files that are not being served by Django, for example, with an Apache server?
What you would then require is some way for this Apache server to use Django as an authentication source.
This django snippet describes such a method. It creates an access handler in Django which is used by Apache when a request for a static file comes in that needs to be protected:
<Location "/protected/location">
PythonPath "['/path/to/proj/'] + sys.path"
PythonOption DJANGO_SETTINGS_MODULE myproj.settings
PythonOption DjangoPermissionName '<permission.codename>'
PythonAccessHandler my_proj.modpython #this should point to accesshandler
SetHandler None
</Location>
Hope this helps, the snippet was posted a while ago, so things might have changed between Django versions :)
More efficient serving of static files through Django is being looked at currently as part of Google SOC project. For WSGI this will use wsgi.file_wrapper extensions for WSGI if available, as it is for mod_wsgi, and req.sendfile() if using mod_python. It will also support returning of headers such as 'Location', 'X-Accel-Redirect' and others, which different web hosting mechanisms and proxy front ends accept as a means of serving up static files where location is defined by a backend web application, which isn't as effecient as front end for serving static files.
I am not sure if there is a project page for this in Django wiki somewhere or not, but the code changes are being committed into the branches/soc2009/http-wsgi-improvements branch of Django source code repository.
You needn't strictly wait for that stuff. It is just putting a clean and portable interface in place across the different mechanisms. If using nginx as front end in front of Apache/mod_wsgi, you could use X-Accel-Redirect now. If using Apache/mod_wsgi 3.0 and daemon mode, you could use Location now, but do need to ensure you set up Apache correct. Alternatively, you could implement your own WSGI middleware wrapper around the Django application which looks for some response header of your own to indicate file to be returned and which uses wsgi.file_wrapper to return that instead of actual response returned from Django.
BTW, the authentication hook mechanisms listed for both mod_python and mod_wsgi by others would use HTTP basic authentication, which isn't what you wanted. This is presuming you want files to be protected by Django form based login mechanism using cookies and backend sessions.

Django File Access Security

I want to restrict access to all but a few selected files per a user, but if I type: /media/userdocuments/FILENAME django happily spits back the file for even users who aren't logged in. How can I integrate the permission framework to work around this?
Thanks!
EDIT: I realize that the django development server is insecure, so I guess the question is: How would I do that in a production environment with apache, lighttp, etc.
Use RewriteMap along with a script that connects to Django and verifies permissions, rewriting to a "disallowed" URL on auth failure.