Django- session cookies and sites on multiple ports - django

I have multiple Django projects running on one server using gunicorn and nginx. Currently they are each configured to run on a unique port of the same IP address using the server directive in nginx. All this works fine.
...
server {
listen 81;
server_name my.ip.x.x;
... #static hosting and reverse proxy to site1
}
server {
listen 84;
server_name my.ip.x.x;
... #static hosting and reverse proxy to site2
}
...
I came across a problem when I had 2 different projects open in 2 tabs and I realized that I could not be logged into both sites at once (both use the built-in Django User model and auth). Upon inspecting the cookies saved in my browser, I realized that the cookie is bound to just the domain name (in my case just an ip address) and it does not include the port.
On the second site, I tried changing SESSION_COOKIE_NAME annd SESSION_COOKIE_DOMAIN, but it doesn't seem to be working and with these current settings I can't even log in.
SESSION_COOKIE_DOMAIN = 'my.ip.x.x:84' #solution is to leave this as default
SESSION_COOKIE_NAME = 'site2' #just using this works
SESSION_COOKIE_PATH = '/' #solution is to leave this as default
#site1 is using all default values for these
What do I need to do to get cookies for both sites working independently?

Just change the SESSION_COOKIE_NAME. The SESSION_COOKIE_DOMAIN doesn't support port numbers afaik. So they are all the same for your apps.

Another solution that doesn't require hard-coding different cookie names for each site is to write a middleware that changes the cookie name based on the port the request came in on.
Here's a simple version (just a few lines of code).

Related

Why does Django allow incoming connections not specified in ALLOWED_HOSTS?

Scenario -
Someone is requesting a url served by a Django app. His IP is 3.3.3.3 . It could be a client but could be a server too, I don't know at the time of the request.
In project settings file, there is
ALLOWED_HOSTS = ["1.1.1.1", "2.2.2.2"]
He (3.3.3.3) is still served. What are the allowed hosts for then?

Django session cookie marked as "third party" and blocked by Firefox

When I log in to my Django-based server using Firefox, the cookie passed to the browser gets marked as "Third Party" and thus gets blocked by default, with no option offered to create an exception, even though the cookie shows as being from "https://servername" which is identical to the URL. I found that if I access the server as "https://servername.domain.lol" instead of directly as "https://servername", the cookie gets marked correctly as first-party. I really don't want to force all users to use the FQDN instead of just the server name. Is there some way in Django or in my Nginx reverse proxy to set some header or something such that the browser will recognize that the cookie belongs to this site?
How did you get your DNS server to respond without the domain?
Nevertheless, besides from configuring the DNS correctly I would suggest to simply let nginx respond with the FQDN. Either by a redirect or by returning a 301.
server {
listen 443;
server_name servername servername.domain.lol;
return 301 https://servername.domain.lol$request_uri;
}

Hosting a django project behind proxypass

I have hosted to django admin project on a local machine X.
http://10.4.x.y/myapp/admin works.
I have an external IP on another machine Y and i am doing a proxy pass
from the Y to X.
http://proxypassname.com/myapp/admin works.
But, When i click the link "Save" or "Save continue editing" button after editing in admin page, it redirects to local machine ip (i.e. http://10.4.x.y/myapp/blah_blah_blah).
How to make sure that the django project redirects to proxypass name instead of local IP?
This is happening because the admin redirects to IP it thinks it has. It gets in in the HTTP request's header.
However, the fix is very easy. Assuming you proxy server implements the X-Forwarded-For standard, it could be easily fixed.
in your settings.py, simply set:
USE_X_FORWARDED_HOST = True
and restart your Django.
If that doesn't work, you can try to see if your proxy sets a different kind of header, and write a middleware that does the same thing. It's the first example on Django's documentation chapter on middleware
I did these two things and it worked.
Whenever you add a ProxyPass, you should add ProxyPassReverse
SITE_ID should be set to the domain where you want to point this django project.

Set domain for cookie (localhost) in IE

I need to set cookie's domain for localhost and I'm using internet explorer. I tried:
Response.Cookies["MyCookie"].Domain = ".local";
but it didn't work, because cookies value and domain are later set to null. Any idea?
Thanks
I suppose this question is related to your local development environment. localhost does not map to the local domain, e.g. pinging localhost.local should not work.
In Windows environments I successfully worked with domain cookies by updating the hosts file with a statement like this:
127.0.0.1 localhost localhost.domain.com
Now you can point your browser to localhost.domain.com and set the cookie's domain property to domain.com. You may need to make this FQDN available to your runtime (in e.g. Tomcat it worked out of the box).

When using sub-domains for a Django site, how can you share django logins across sub-domains on localhost?

I want to let the same user session span across:
site.com
sub1.site.com
sub2.site.com
I got this to work in production by setting SESSION_COOKIE_DOMAIN to ".site.com", but it doesn't work for me on localhost/dev servers. How do you get it to work for localhost sub-domains? When I change the SESSION_COOKIE_DOMAIN on the dev server to the production website domain or ".localhost", django auth logins completely stop working (I'm unable to ever login, no cookie is created on localhost).
I think I got a workaround solution, but couldn't use localhost. I could only get it working for a test ".com" domain that maps to 127.0.0.1.
In my /etc/hosts file (on OSX:)
127.0.0.1 test.com
127.0.0.1 sub1.test.com
127.0.0.1 sub2.test.com
Then on my development settings.py:
SESSION_COOKIE_DOMAIN=".test.com"
I could not get this working with plain "localhost", it seemed I needed the ".com" string in there to get it working. So then I could login and have cross subdomain auth cookies using sub1.test.com:8000 and sub2.test.com:8000 in my browser.