Reputation: 3149
Well, this is a bit complicated, but let me explain myself. I want to create a RESTful service. This service will contain users, but not in a classic way.
I want to create users based on random hashes, I will use uuid
to do that. And the most important thing is that I will not need username
, password
, email
or full_name
(?). This type of user will authenticate via a GET parameter on a view, only using its username
, not anything else.
I read some articles on extending Django user, yet I couldn't find satisfying explanation especially for this case.
Now, I can hear questions like "Why would anyone ever need especially passwordless User model, and especially thinking that it is quite insecure.". So, this part is especially for the ones who needs a logical explanation to understand such a request.
In service, I want to have three group of users:
anonymous users
: the ones who do request some data on serveruuid users
: the ones who have a unique id. Why do I need this type? Because I want to track those users' requests and response special data for them. These kind of users will also be removed if they are inactive for specific several days. I think I can do it by cron jobs.admin
: This is me, reaching admin panel. That is all.I think this explains enough.
Upvotes: 1
Views: 974
Reputation: 2757
Django supports multiple backend authentications. As Luis Masuelli suggested you can extend the model to add more fields. But in your scenario, specifically you want to implement a custom authentication method. I woudl go about treating uuid as username and setting password as None.
So, in my settings.py:
AUTH_USER_MODEL = 'app_name.MyUUIDModel'
# REMOVE ALL PASSWORD Validators
In my app_name/models.py:
from django.contrib.auth.models import BaseUserManager
class MyUUIDManager(BaseUserManager):
def create_user(self, uuid):
user = self.model(
uuid=self.normalize_email(email),
)
user.set_password(None)
user.save(using=self._db)
return user
def create_superuser(self, uuid):
user = self.create_user(uuid)
user.save(using=self._db)
return user
def get_by_natural_key(self, email):
return self.get(**{self.model.USERNAME_FIELD: email})
class MyUUIDModel(AbstractBaseUser):
uuid = models.CharField(max_length=36, unique=True)
USERNAME_FIELD = 'uuid'
objects = UUIDModelManager()
def save(self, *args, **kwargs):
super(MyUUIDModel, self).save(*args, **kwargs)
At this point, if you run createuser or createsuperuser Django command, you may be able to create the user. The next bit is where the authentication needs to be done. You can simply check if the UUID exists in your DB and return true when authenticate() is called from the view.
Add authentication backend in the settings.py file:
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'app_name.auth.MyBackend'
]
Create a file app_name/auth.py with contents SIMILAR to below:
class MyBackend(object):
def authenticate(self, username=None, password=None):
# Check if username i.e. UUID exists
try:
my_uuid = MyUUIDModel.objects.get(uuid=username)
except MyUUIDModel.DoesNotExist:
return None
return my_uuid
More more details refer to: https://docs.djangoproject.com/en/1.9/topics/auth/customizing/
Upvotes: 1