Skip to content

Django Authentication Basics

Reece Mathews edited this page Jan 29, 2021 · 29 revisions

A VERY BASIC and not very secure cookie-based authentication system has been implemented in Django for the OPS. The actual storage and management of the authentication (in the database) is secure, but how clients authenticate (by passing simple cookies and plain-text passwords) is not.


Django Authentication Model

Django User Profile Application

Creating & Editing New Users

Adding User to Layer Group

Setting Season Group (public/private)

Basic Authentication Example

IP Authorization


Django Authentication Model

Telling Django to include the models (database schema) for authentication is as simple as including the following lines in the settings.py file.

Add 'django.contrib.auth', to INSTALLED_APPS

Add 'django.contrib.auth.middleware.AuthenticationMiddleware', to MIDDLEWARE_CLASSES

With those two lines on the syncdb command all the framework needed to store basic Django users is created.

Django User Profile Application

To have a custom user profile tied to each Django user (containing custom permissions) we need to add a few things in settings.py AND create some new files.

The new files created are in ops/opsuser/*. The only key one is models.py:

from django.contrib.gis.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save

class UserProfile(models.Model):
	user = models.OneToOneField(User,related_name="profile", unique=True)
	rds_season_groups = models.ManyToManyField('rds.season_groups',null=True)
	rds_layer_groups = models.ManyToManyField('rds.layer_groups',null=True)
	accum_season_groups = models.ManyToManyField('accum.season_groups',null=True)
	accum_layer_groups = models.ManyToManyField('accum.layer_groups',null=True)
	snow_season_groups = models.ManyToManyField('snow.season_groups',null=True)
	snow_layer_groups = models.ManyToManyField('snow.layer_groups',null=True)
	kuband_season_groups = models.ManyToManyField('kuband.season_groups',null=True)
	kuband_layer_groups = models.ManyToManyField('kuband.layer_groups',null=True)
	layerGroupRelease = models.BooleanField(default=False)
	seasonRelease = models.BooleanField(default=False)
	createData = models.BooleanField(default=False)
	bulkDeleteData = models.BooleanField(default=False)
	isRoot = models.BooleanField(default=False)
	
	def create_profile(sender, instance, created, **kwargs):
		if created:
			profile, created = UserProfile.objects.get_or_create(user=instance)
			profile.rds_season_groups = [1]
			profile.accum_season_groups = [1]
			profile.snow_season_groups = [1]
			profile.kuband_season_groups = [1]
			profile.rds_layer_groups = [1,2]
			profile.accum_layer_groups = [1,2]
			profile.snow_layer_groups = [1,2]
			profile.kuband_layer_groups = [1,2]
			
	post_save.connect(create_profile, sender=User)

This file defines an additional schema in the database for a user profile. Note the last line post_save.connect(create_profile, sender=User) which tells Django to create a new profile with a 1-1 relationship with a Django user each time a new user is created.

In settings.py we need to add the following:

Add the line AUTH_PROFILE_MODULE = 'opsuser.UserProfile'

Add 'opsuser', to INSTALLED_APPS

Creating & Editing Users

One can use the createUser() view (Matlab code not completed yet for this) or follow the procedure outlined below.

  1. Log on to the OPS server (e.g. ops3)
  2. Become user root sudo -i
  3. Activate the virtual environment source /usr/bin/venv/bin/activate
  4. Change directory cd /vagrant/conf/tools/
  5. Run gedit createUserExample.py. Usually this is just changing the userName, userEmail, and userPassword fields. Typically all users have access to public (id 1) and private (id 2) seasons and all users have access to uncategorized (id 1) and standard (id 2) groups so the settings [1,2] are good for layer groups and seasons groups for everyone.
  6. Start the Django shell python /var/django/ops/manage.py shell.
  7. Run from the python command line execfile('createUserExample.py') (or exec(open("./createUserExample.py").read()) for python3)
  8. From python command line, enter quit when finished.

Adding a user is shown below:

from django.contrib.auth.models import User

# set new user properties
userName='FILL_IN_USERNAME'
userEmail='[email protected]'
userPassword='FILL_IN_PASSWORD'

# create the new user
newUser = User.objects.create_user(userName, userEmail, userPassword)

# set the user profile options (example for a typical cresis user)
newUser.profile.rds_layer_groups = [1,2]
newUser.profile.accum_layer_groups = [1,2]
newUser.profile.kuband_layer_groups = [1,2]
newUser.profile.snow_layer_groups = [1,2]
newUser.profile.rds_season_groups = [1,2]
newUser.profile.accum_season_groups = [1,2]
newUser.profile.kuband_season_groups = [1,2]
newUser.profile.snow_season_groups = [1,2]
newUser.profile.layerGroupRelease = True
newUser.profile.bulkDeleteData = False
newUser.profile.createData = True
newUser.profile.seasonRelease = True

# save the user profile
newUser.profile.save()

To add/remove permissions from an existing user, root users can use the alterUserPermissions() view. User authentication information is stored in the auth_user table. The opsuser_userprofile table maps the auth_user ID to the opsuser ID. The particular layer group can be found in the SYS_layer_groups table (e.g. rds_layer_groups). The SQL command might look like INSERT INTO opsuser_userprofile_rds_layer_groups (userprofile_id,layer_groups_id) VALUES (38,7). Administrators can also execute the following commands in the Django shell using Django:

from django.contrib.auth.models import User

userObj = User.objects.get(username_exact='ENTERNAMEHERE')
userProf = userObj.profile

# TO ADD SOMETHING
userProf.rds_layer_groups.add(SOMEGROUPID)

# TO REMOVE SOMETHING
userProf.rds_layer_groups.delete(SOMEGROUPID)

# TO SAVE CHANGES
userProf.save()

Adding User to Layer Group

To add user USERNAME to layer group GROUP, run the following query:

INSERT INTO opsuser_userprofile_rds_layer_groups (userprofile_id,layer_groups_id) VALUES ((SELECT opsuser_userprofile.id FROM auth_user,opsuser_userprofile WHERE auth_user.username=''USERNAME'' AND auth_user.id=opsuser_userprofile.user_id),(SELECT id FROM rds_layer_groups WHERE name=''GROUP''))

Setting Season Group

Seasons can either be public (group 1) or private (group 2). The season name is usually a string of a form similar to 2011_Greenland_P3. For example, to make the rds season SEASON private:

UPDATE rds_seasons SET season_group_id=2 WHERE name=''SEASON''

Basic Authentication Example

An example would be to check if a user is allowed to create data. From createPath in views.py:

models,data,app,cookies = utility.getInput(request) # get the input and models
	
userProfileObj,status = utility.getUserProfile(cookies)
if status:
	if not userProfileObj.createData:
		return utility.response(0,'ERROR: USER NOT AUTHORIZED TO CREATE DATA.',{})
else:
	return utility.response(0,userProfileObj,{});

The cookies (from whatever client, see getData in utility.py) are retrieved in the call to getInput. Then the function getUserProfile(cookies) is used to retrieve the user profile object. At that point it's just logical checks against permissions.

IP Authorization

Django is setup to be open to all IP addresses from the Apache interface. Access to write interfaces is supported by a Django decorator and IP addresses need to be added to the authip.py file located at /var/django/ops/ops.

Location           | IP Address range
-------------------+------------------
Lindley Hall       | 129.237.14[45].{0-255}
Nichols Hall       | 129.237.16[45].{0-255} 
Indiana University | 149.165.2{29,30}.{0-255}
VM Net             | 10.0.2.2, 127.0.0.1, 192.168.111.{0-255}