How can I secure a Django site - django

I have a working django site - up-and-live, working just fine. It uses Django's contrib.auth for authentication. It's hosted on Heroku. I would like to set up a clone of this site for demo purposes, but would like to add an extra layer of security around the site, which would be a very simple password-protection. Doesn't have to be bulletproof or unhackable - just enough to put 'muggles' off trying.
This authorisation layer should not in any way interfere with the site auth itself. It's just an outer ring (check once, store access rights in session). Because the site is hosted on Heroku this is not something I can do at the web server level - it has to be part of the app itself.
My nuclear option is to create a django app (working title 'perimeter') which would enforce this, but if anyone knows another way to do this, I would be really grateful.
Core features include:
Some mechanism for generating short tokens (< 8 chars)
Some mechanism for logging tokens against an email address
Prompt users for a token / email combination on first access of site
Unrestricted access to site thereafter (standard auth model kicks in at that point)
Typical user journey is:
Bob asks site owner (me) for access to demo site
I generate a token for Bob and send it him along with the site URL
Bob clicks on the link, gets redirected to page to input his email and the token
If the token is valid (expires after X hours / days), store in session, let Bob in.
If the token is not valid, 403 (/401).
(You may wonder why securing a copy of website that is already public makes any sense. It's because the site is a members-only site, and on the demo version it will be 'auto-enroll' so that people can see what it's like inside the site without having access to the real data. However, I would like to be able to track users on it.)
[UPDATE: alternative]
A blunt alternative is to add the token to the URL I send Bob, ignore his email, and simply validate the token itself. That would work so long as Bob always uses the URL in the email.

I have created my own solution to this - meet Django-Perimeter.
This app isn't packaged (yet) so you'll need to clone the source and add it in manually to your own django site, but it does work. It provides the ability to generate access tokens, and then secure access to the site (the entire site, not parts of it) using those tokens.
[UPDATE]
This is now available via PyPI - http://pypi.python.org/pypi/django-perimeter
You can install using pip install django-perimeter

Related

is it possible to have google-auth within django template?

I have a django app that uses Google's allauth for signing up and logging in, but it first takes me to a google url and to sign in, i.e., my header and other parts of my site are not visible. Once I log in through my google account I'm redirected, so the logic works fine.
I'm just wondering if it's possible to have that process be done on my site.
For social auth I prefer to use Django Social Auth.
In regards to what OP is asking, I've never seen that before and as a user of a system I wouldn't want it like that. Who could grant me that OP wouldn't also be storing other relevant details of mine to perform that operation?
In fact, the idea of social auth is that one is passing the responsibility of authentication to Google or any other provider, hence going to their system to do that operation and then redirected back.

How to use AWS Cognito as a unified SSO?

I would like to have only one login screen, registration, profile and password recovery for all projects in my company. Basically a unified login or SSO.
So I made these screens using AWS Cognito and hosted them on the sso.mycompany.com domain and it's working fine.
But now I need to implement these screens in my other projects. How can I do this? I can't just copy the files, as this was done in Vue.js, and I would like to put these screens in projects done in Laravel, Wordpress, React, etc;
I thought of using an iframe loading sso.mycompany.com, but how do I return user data after login to the app that opened the iframe?
Basically that's it, I have authentication screens hosted on the sso.mycompany.com domain and I would like to use them on projectx.com, projecty.com, mycompany.com, etc.
Here is one solution that might work for you and might give you some ideas on how you could put together a solution. Unfortunately, Cognito out of the box doesn't come with a unified/universal login experience that you require. It also doesn't come with a lot of other features you might see from the big IdP platforms, but that is another discussion for another time :) The whole foundation of this solution is based off of a single domain, cookies and JWTs(access token, id token and a refresh token). It will still work for your apps on other domains, but the experience for your end users will be a bit sub optimal compared to if all your apps were on the same domain.
Because an app like projectx.com sits on a different domain then sso.mycompany.com, you have to somehow get a access token over to projectx.com after the user logs in through mycompany.com. You can simply just pass the access token through as a query param when you redirect the user back to projectx.com after a successful login on sso.mycompany.com.
I had a much longer answer with details, but stackoverflow won't let me post because it thinks my answer is spam??? Check my profile on how to contact me if you want the longer version with details.

Session Hijacking in Django 1.7.7 and python3

I have developed a small application for submitting some data to database server(Oracle 11g). When we are reviewing security of this small application, we observed as follows:
1. We have deployed django with https and all secure configurations like Secure Cookie and Secure Session, No Cache, etc.
2. Using BURP tool for this sample review
3. We have created two different user in this system say Normal User and Admin User
4. Opened 2 browsers(Mozilla and IE 11), On mozilla we login with Admin user and captured session id using burp tool.
5. On second browser we login with Normal user and replaced session id Normal User with Admin User.
6. whoila......On second browser, I got Admin user access by just changing the session id
I have used default session backend for this application.
I would like to know whether this is flaw in django and how to resolve this issue..
Thanks in advance
This is an inherent risk of using session-based identification. It's called session hijacking, and if you search for that term you will find lots of information.
Mitigations generally have one of two goals: making it harder to steal the token, or making the damage less severe if it is stolen. In the former camp are techniques like using HTTPS and SESSION_COOKIE_HTTPONLY. In the latter are things like limiting the length of a valid session (SESSION_COOKIE_AGE). In the end, though, it's difficult or impossible to stop someone from impersonating another user if they get their token, since that's the very thing that establishes identity.

Django set django session cookies programmatically

I am creating a saas, software as a service site with django.
Due to the project requirements the users are inside schemas/tenants, for that im using the fantastic django-tenant-schemas app, one user can have accounts inside different schemas (they share username and password) ... i want to let the user move throught the different schemas they are in more or less freely ... for that i have created a view where the user can select on what schema he wants to be on.
When i use an application wide cookie session that is when i have the cookie setting as ".domain.ext" (django documentation) that works fine but its NOT the behaviour we really want for our application.
What we really need is to be able to have different versions of the app on different browser tabs.
So we have to set the cookie configuration to "domain.ext", then everything breaks because the original view is on one tenant and the next view (where the just logged user really belongs) is inside other tenant then the old cookie is deleted.
So the question is how can i programmatically set the cookie correctly on the new view so the user that really belongs to that tenat is still authenticated.
Or is there any alternative approach we could use for that? Any examples?
EDIT TO CLARIFY as demanded:
Person A belongs to 2 schemas SH1 and SH2 on both of them he has the same username and password.
On every password change the password hash is replicated on all the schemas they belong to so they dont have to remember specific passwords or usernames.
When the person is logged on SH1 the url will be sh1.domain.com when he is logged on SH2 the url will be sh2.domain.com
So lets say the person is now logged on schema SH1, he decides to switch to schema SH2, to be able to do that i need the user to still been authenticated so that view has to be on the SH1 schema, but then its redirected to the new schema force authenticating the user but since the cookie is set as domain specific (default django behaviour) when the user lands on the next url sh1.domain.com/whatever the previous cookie is deleted and thus he has to log in again to be able to access.
If I'm understanding correctly, you want the ability to have the behavior of a cross-domain cookie, but without actually using a cross-domain cookie.
The immediate answer that comes to mind is "well, use a cross-domain cookie". This is pretty much the vanilla example of a situation where you'd want to use use a cross-domain cookie. Engineering a complex solution so that you can avoid using the simple solution never ends well :-) Unless there's some other constraint in play that you haven't revealed, I'd start by questioning whether you shouldn't just be doing this the easy way.
However, assuming there is a good reason (and, frankly, I'd be interested to know what that is), the problem you're going to face is that browser security is essentially trying to stop you doing exactly what you're proposing. You want to know, from domain SH2, whether something has happened to a cookie set on domain SH1. That's exactly the situation that cookie security policies are designed to prevent.
The only way you're going to be able to work around this is to have a third party that can share knowledge. When user A logs into SH1, you do password authentication as normal - but you also post a flag somewhere that says "User A is now on SH1". When A logs into SH2, you post the corresponding flag. If A goes back to SH1, you check against the central source of truth, discover that they're currently on SH2, and force a login.
You probably could do this by manipulating cookies and session keys, but I suspect an easier way would be to use an Authentication backend. What you'll be writing is an authentication backend that is very similar to Django's own backend - except that it will be making checks of cross-domain login status against the central source of truth.
How you implement that "source of truth" is up to you - an in memory cache, database table, or any other source of data will do. The key idea is that you're not trying to rewrite cookies so that the same cookie works on every site - you're keeping each site's cookies independent, but using Django's authentication infrastructure to keep the cookies synchronised as a user moves between domains.

AllAuth Installation

I'm attempting to install and configure Django AllAuth and I've run into a plethora of obstacles. I'm afraid I'm simply missing a few basic concepts which might clear some things up.
In order to get basic social authentication working what setup needs to be done inside the social provider (Facebook, Twitter, etc.)
If this is the case then how would one develop locally because at first glance of Twitter's API setup it asks for redirect URLs which would get hairy considering everything right now is hosted locally.
When I try and go to /accounts/login/ it redirects to /accounts/profile/ every time. Can't seem to figure out what's causing this redirect.
I was previously using Userena for my user authentication and was going to add Django-social-auth but when I got into it that was giving me difficulty. I then found AllAuth which seemed to fit my needs perfectly but again, having some issues. Can anyone weigh in on this decision, would you recommend one over the other and if so why?
Facebook Error:
"Given URL is not allowed by the Application configuration.: One or more of the given URLs is not allowed by the App's settings. It must match the Website URL or Canvas URL, or the domain must be a subdomain of one of the App's domains."
When I click okay it redirects back to my site. My browser gives me a security error and when I proceed through that I end up back at my site displaying:
"Social Network Login Failure
An error occurred while attempting to login via your social network account."
1) Have a look here: https://speakerdeck.com/tedtieken/signing-up-and-signing-in-users-in-django-with-django-allauth
(specifically, slide 61 and above)
2) Simply use 127.0.0.1:8000 in your redirect URLs
3) By default allauth redirects to LOGIN_REDIRECT_URL, which is set out of the box to /accounts/profile/: https://docs.djangoproject.com/en/dev/ref/settings/#login-redirect-url
4) As I am the author of allauth I will skip answering this question myself. Browse through the complete presentation referred to by 1) -- the initial slides provide a good comparison of the various options.