1

I have two different classes of user for a Django-based event registration system. Let's call them "Registrant" and "Staffer".

These two are not mutually exclusive, and I see no reason not to use the same User model for both classes (with a flag to distinguish them).

A Registrant can sign in by verifying their identity with a third-party API, and can then register for an event.

A Staffer has access to Django Admin, and can manage events. I do not trust the third-party API to sufficiently authenticate somebody who has Staffer access as, while it does request personal information to identify someone, it doesn't ask for anything as secure as a password. I therefore want Staffers to enter in a password instead of authenticate via the third-party API.

I see that I can write a custom auth backend in Django, and I can customise the default User model to suit my needs regarding aforementioned flags (though I suspect the default is_staff) flag might be sufficient).

Unfortunately, while I know that I can use multiple authentication backends, I am quite stuck working out how to:

a) determine which authentication backend to use (e.g. use the Registrant auth backend in the frontend, and the Staffer auth backend in the Admin) b) only allow users authenticated via the Staffer auth backend to access the Admin

Can anybody please point me in the right direction?

Apologies for the lack of code; I'm re-working the auth system from scratch (because the previous version was really badly hacked together) and I don't quite know where to start.

EDIT: There is some useful info at Django Multiple Authentication Backends Based On Status, but because I would like to use the same User model for both user classes, and both auth backends would request different types of credentials (e.g. one requesting a password, the other not), I need to think more about how to tackle this.

1
  • Please provide enough code so others can better understand or reproduce the problem. Commented May 27, 2022 at 4:39

2 Answers 2

1

The answer to "determine which authentication backend to use" is quite simple, you simply don't need to. As specified in the documentation when you call the authenticate() function Django tries each of the AUTHENTICATION_BACKENDS in turn until one either returns a user or raises a PermissionDenied exception.

Also if you look at the default backend's code [GitHub], if no username or password is passed in, it just returns None. You would need to implement your backend in a similar manner so that if the credentials you expect aren't passed in you should just return None and let the other (possible) backends handle it.

For "only allow users authenticated via the Staffer auth backend to access the Admin" you can override the default admin site and override the has_permission method:

from django.contrib import admin
from django.contrib.auth import BACKEND_SESSION_KEY

class MyAdminSite(admin.AdminSite):
    def has_permission(self, request):
        """
        Return True if the given HttpRequest has permission to view
        *at least one* page in the admin site.
        """
        try:
            backend_path = request.session[BACKEND_SESSION_KEY]
            staffer_backend = backend_path == "path.to.StafferBackend"
            return request.user.is_active and request.user.is_staff and staffer_backend
        except KeyError:
            return False

And then in an apps.py in one of your apps:

from django.contrib.admin.apps import AdminConfig

class MyAdminConfig(AdminConfig):
    default_site = 'myproject.admin.MyAdminSite'

And finally in your setting replace 'django.contrib.admin':

INSTALLED_APPS = [
    ...
    'myproject.apps.MyAdminConfig',  # replaces 'django.contrib.admin'
    ...
]
Sign up to request clarification or add additional context in comments.

Comments

0

If I had this problem I would use an inherited model for each of them, making username as the default login in staff and email on the registrant, extending both the BaseUser model.

To select with Auth backend I just set a checkbox or build different URLs to login.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.