Django: setting a different SESSION_COOKIE_DOMAIN depending on the domain - python

I use the same Django project for various domains. Some are subdomains, some are entirely different domains, so I have these domains operating the same Django site:
a.example1.com
b.example1.com
c.example1.com
example1.com
example2.com
I do not use the sites framework for reasons unrelated to this query, and I have a single settings.py for all sites, which I'd like to maintain.
When someone logs onto a subdomain, I'd like them to be logged onto any of the other subdomains as well. In fact, if it were possible I'd like them to be logged onto the other sites as well but I doubt this is possible. In order to achieve logging into all subdomains at the same time, I set the following variable in settings.py:
SESSION_COOKIE_DOMAIN=".example1.com"
This works as advertised and the logins are now working across different sites. However, I am not able to log onto any of the other domains anymore (I assume the cookie is set for the wrong domain and subsequently not properly recognized). What I assume I should do is somehow set SESSION_COOKIE_DOMAIN to either .example1.com when on the main site, or .example2.com when I'm on a different site. But how to achieve this?
Here is a similar question and this answer seems to do what I am looking for through a lightweight solution. However, this is written for older Django versions. I tried rewriting this for Django 3 as follows:
class CrossDomainSessionMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
try:
if request.COOKIES:
host = request.get_host()
# check if it's a different domain
if host not in settings.SESSION_COOKIE_DOMAIN:
domain = ".{domain}".format(domain=host)
for cookie in request.COOKIES:
if "domain" in request.COOKIES[cookie]:
request.cookies[cookie]['domain'] = domain
except:
pass
return self.get_response(request)
But this doesn't seem to work. This condition:
if "domain" in request.COOKIES[cookie]:
Is simply never met. Not sure what I should change.

Related

Django multiple sites : Prevent cross-site authentification

I'm currently developing 2 different sites at the same time: one of them is a heavily customized django-admin interface, and the other a "stand-alone" website that will share it's database with the previous one .
Even though they are related, I'd like my users not to loosely identify between the two sites : they are both able to be independant of the other.
However, a problem arises when someone is logged in the "admin" site : when they go to the other website, they are automatically logged. Won't happen the other way unless I allow it though, as the admin site requires special permissions in the User model.
I already created an UserProfile that can differentiate an user of one of the sites or of the both.
So, knowing all this, how can I make sure that the customers of the admin site don't get to be authenticated when in the other web site (without, of course, logging them out from the first one) ?
Thanks !
EDIT : To format it better, here is what I got , summed up :
One admin application / site                                                      Both running
One related application / site                                                   on same server,
                                                                                      sharing settings and urls.py
If some is logged in admin, I want to require them to create a new session to log on [related site] : this, without logging them off the admin site.
What changes should I do to this configuration to achieve this ?
Put different SESSION_COOKIE_DOMAIN and SESSION_COOKIE_NAME for each appication. Hope this solve your issue.
SESSION_COOKIE_DOMAIN = 'site1.com' #site2.com for other
SESSION_COOKIE_NAME = 'sid1' #sid2 for other

how to use multiple domains and mask a django project

I have a Django website that's configured on a particular domain example.com. Now I'm planning to use the same website for different countries where I have to use their language. For example China, I'm planning to create a sub domain chinese.example.com which will point to exactly the same example.com project but the language will be switched to chinese. Also I would like to mask this chinese.example.com sub domain with another domain chinaexample.com. Please advise how to accomplish this using Apache & Django.
First step - make sure that all of your domains are added into 'ALLOWED_HOSTS' in django config.
Next - if you will have some content that will be available only for particular domain, it will be handy to use sites framework built into django. But if you want to have one language on multiple domains and want some content to be available for language, not for domain, better solution might be to create own method for assigning content to domain (or language).
Third step - write middleware that will check your domain and activate language assigned to it. Example middleware can look like this:
class DomainLanguageMiddleware:
def process_request(self, request):
try:
host = request.META['HTTP_HOST']
host_port = host.split(':')
if len(host_port) == 2:
host = host_port[0]
if host in settings.LANG_MAP:
request.LANG = settings.LANG_MAP[host]
translation.activate(request.LANG)
request.LANGUAGE_CODE = request.LANG
except KeyError:
pass
This code is using LANG_MAP setting, that should be an dictionary containing domain as key and language assigned to that domain as value.
Using that solution, all domains or subdomains can point to one django instance, with one settings.py file.

How to make Django test client send requests to different subdomains

I am using the django-subdomains project to enable subdomains in my django project, which works fine.
However, when writing tests, I cannot figure out how to make the Django test client send requests to different subdomains.
It only sends requests to the root domain even if I change the ROOT_URLCONF to point to one of the entries in SUBDOMAIN_URLCONFS with #override_settings. But it works if I directly change the ROOT_URLCONF in settings.py to the desired subdomain urlconf, which is obviously an unacceptable solution.
Also tried to subclass the Django TestCase class and set the "url" field to the subdomain urlconf but the request is still going to root, resulting in 404.
Finally, I tried to use subdomains.utils.reverse to get an absolute url, but the test client does not accept this at all.
This question may be related to Django Test Client and Subdomains. Someone mentioned in a comment that a hack has been used to solve this. Please elucidate said hack or even better, a proper solution to address this surely not-so uncommon use case.
HTTP_HOST = 'rede.example.com'
class TestIndexView(TestCase):
def setUp(self):
self.url = subdomain_reverse('network_index', subdomain='rede')
def test_render(self):
response = self.client.get(self.url, HTTP_HOST=HTTP_HOST)
self.assertEqual(response.status_code, 200)

Can I use Django to prevent direct access to an image file?

I'd like to prevent my web users from simply right clicking an image and copying/sharing the URL. Certain authenticated users have access to certain images, and I'd like to enforce this as much as possible. Non authenticated users should have no access to image files.
It's generally recommended to avoid storing/fetching images from a DB, due to performance issues, from what I have read.
I've considered having a function that reads the file (server side, in python) and inserts it into the webpage (base64 encoded, possibly, or some other way) in the Django view functions. Combined with an .htaccess file that denies external requests, this would likely work, but it seems like it'd be resource intensive.
Is there any other options for enforcing this rule? I realize users can screenshot, save images, etc, but it's my responsibility to enforce these restrictions as much as possible, what are my best options?
edit: I have no experience using a CDN, but would be willing to use this if it's a viable option that covers these needs.
I'll bite.
Session Middleware - not elegant, but it will work
You'll want the images you don't want served publicly to not be served through your standard apache/django static files config.
your session middleware can then check all incoming requests for the path and if the path is your image directory (such as /privateimg/) and the user is not authenticated you can bounce them back out or replace it inline with another image (such as one that has a watermark).
You can check out the django docs on how session middleware works https://docs.djangoproject.com/en/dev/topics/http/sessions/
People can still pass your links around, but only authenticated users can actually see the contents of said links (called gating your content)
To elaborate:
settings.py
GATED_CONTENT = (
'/some_content_dir/', # This is a directory we want to gate
'.pdf', # maybe we want to gate an entire content type
)
MIDDLEWARE_CLASSES = (
... # Out of the box middleware...blah blah
'yourapp.somemodule.sessionmiddleware.GatedContent',
)
Then you have the following app structure
yourapp
|-somemodule
|-sessionmiddleware.py
Now to the meat (yum!)
sessionmiddleware.py
class GatedContent(object):
"""
Prevents specific content directories and types
from being exposed to non-authenticated users
"""
def process_request(self, request):
path = request.path
user = request.user # out of the box auth, YMMV
is_gated = False
for gated in settings.GATED_CONTENT:
if path.startswith(gated) or path.endswith(gated):
is_gated = True
break
# Validate the user is an authenticated/valid user
if is_gated and not user.is_authenticated():
# Handle redirect
You might be interested in XSendfile.
This is most [elegant and] performance choice IMO: actual files will be served by you webserver, while access control to this files will be done using your Django app.
You may google for "django xsendfile", there are lot of useful posts.

Authenticating user from SSO + OpenID in django for google apps custom domain

After a lot of reading and researching i found the following library, the most suited to work for my needs: to signup/login a user using a custom google apps domain.
I did the following settings:
GOOGLE_APPS_DOMAIN = 'example.com'
GOOGLE_APPS_CONSUMER_KEY = 'example.com'
GOOGLE_APPS_CONSUMER_SECRET = '*sekret*'
# domain where your application is running
GOOGLE_OPENID_REALM = 'http://*.hudora.biz/'
GOOGLE_OPENID_ENDPOINT = 'https://www.google.com/accounts/o8/ud'
added custom middlewares and other stuff.
But from now, where do i take it further, showing a form and making form posts to urls, how do i ask user information, it is not given in the docs.
Can anybody please help me with it?
How do i give a user the functionality to login/signup?
How do i customize a view?
You are almost there. For the sake of testing it on your localhost following are things you need to do:
You need to register an app at the Google API Console (while registering, put your domain 127.0.0.1:8000 or the exact location where your server is running)
You need to check the scope for your project, eg. calendar or maps etc.
You need to get the secret key.
Once you have got the secret, put them in your settings file, as described above. Change example.com and *.hudora.biz to 127.0.0.1:8000
Import the views from the library views for login and logout and map them to your urls probably login/logout.
This is all that is reqd. Hope it helps!

Categories