HyperSaaS
BackendAuthentication

Overview

Authentication system using djoser, SimpleJWT and django-allauth.

HyperSaaS uses three libraries for authentication:

LibraryPurpose
djoserREST endpoints for sign-up, activation, password reset, email change and account deletion
djangorestframework-simplejwtJWT access and refresh tokens
django-allauthServer-side account pages, and the Django admin's sign-in when DJANGO_ADMIN_FORCE_ALLAUTH=True

The Next.js frontend signs people in with email and password through these endpoints. There is no server-rendered sign-up: allauth's own sign-up pages are closed unless you set DJANGO_ACCOUNT_ALLOW_REGISTRATION=True, because an account created there would skip the API's activation flow.

Authentication Method

The REST API accepts JWTs only:

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "rest_framework_simplejwt.authentication.JWTAuthentication",
    ),
    "DEFAULT_PERMISSION_CLASSES": (
        "rest_framework.permissions.IsAuthenticated",
    ),
}

Send the access token as Authorization: JWT <access_token>. See JWT Tokens for lifetimes and refresh.

Custom User Model

HyperSaaS uses email as the identifier instead of a username:

class User(AbstractUser):
    name = models.CharField(max_length=255, blank=True)
    email = models.EmailField(unique=True)

    USERNAME_FIELD = "email"

    class Meta:
        constraints = [
            models.UniqueConstraint(Lower("email"), name="users_user_email_unique_ignoring_case"),
        ]

Emails are stored lowercase and looked up case-insensitively, so Ana@Example.com and ana@example.com are the same account.

Rate Limits

Signing in, signing up, activation, password and email resets, and password changes are limited per account: by the email or uid in the request, not by IP.

SettingDefaultCovers
THROTTLE_AUTH_ATTEMPTS10/minutePOST /auth/jwt/create/ and djoser's account endpoints

That stops guessing at one account's password and repeated emails to one address. Limiting by IP would lock everyone out at once, since the Next.js server makes these calls for all users. Over the limit, the API returns 429.

Password reset and email reset answer the same whether or not the address is registered, so they can't be used to find out who has an account.

Password Hashing

HyperSaaS uses Argon2 as the primary password hasher:

PASSWORD_HASHERS = [
    "django.contrib.auth.hashers.Argon2PasswordHasher",
    "django.contrib.auth.hashers.PBKDF2PasswordHasher",
    "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
    "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
]

On this page