matthiask / django-authlib

Utilities for passwordless authentication (using magic links, Google, Facebook and Twitter OAuth currently)
https://django-authlib.readthedocs.io/
MIT License
61 stars 11 forks source link

Bug? User can't log - user object is set to none #11

Closed martarho closed 2 years ago

martarho commented 2 years ago

I guess I must continue my quest to get SSO set up :)

Unfortunately it seems I still can't get it to work. I tried creating users as I intend to do (no password) as well as with password - neither of them get to log in. The error is "No matching staff users for email address 'marta@my-domain.com'

I tested it a bit and the problem seems to be on this line: https://github.com/matthiask/django-authlib/blob/80fb597a4b721c5a7590a6b84a3fbd547953cc5f/authlib/admin_oauth/views.py#L41

user_mail has the correct value, but user is set to None.

My app set up:

User model under a specific django app (core)

core/models.py

from django.db import models
from django.contrib.auth.models import (
    AbstractBaseUser,
    PermissionsMixin,
)

from core.managers import UserManager

class User(AbstractBaseUser, PermissionsMixin):
    """Custom user model that supports using login with
    email instead of username"""

    username = models.CharField(default="", max_length=255)
    email = models.EmailField(unique=True, max_length=255)
    archived = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    objects = UserManager()

    EMAIL_FIELD = "email"
    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = ["username"]

    class Meta:
        verbose_name = "user"
        verbose_name_plural = "users"

    def __str__(self):
        return f"{self.email} - {self.username}"

core/managers.py

from django.contrib.auth.models import BaseUserManager

class UserManager(BaseUserManager):
    def create_user(self, email, username, password=None, **kwargs):
        """To create user using custom fields"""
        if not email:
            raise ValueError("Invalid Email!!")
        user = self.model(
            email=self.normalize_email(email), username=username, **kwargs
        )
        if password is None:
            user.set_unusable_password()
        else:
            user.set_password(password)
        user.save(using=self._db)

        return user

    def create_superuser(self, email, username, password):
        """To create superuser using custom fields"""
        user = self.create_user(email=email, username=username, password=password)
        user.is_staff = True
        user.is_superuser = True
        user.is_active = True
        user.save(using=self._db)

        return user
ADMIN_OAUTH_PATTERNS = [
    (r"^.*@my\-domain\.com$", lambda match: match[0]),
    (r"@my\-domain\.com$", "local_admin@my-domain.com"),
]
matthiask commented 2 years ago

I'd assume that either marta@my-domain.com or local_admin@my-domain.com exists and is an active user with is_staff=True?

Did you add authlib.backends.EmailBackend to AUTHENTICATION_BACKENDS? The default django.contrib.auth.backends.ModelBackend doesn't support authenticating using only an email address.

martarho commented 2 years ago

Well, I guess I missed on the authlib.backends.EmailBackend line :) Sorry! Will close this issue.

Thanks again for your help, @matthiask !

matthiask commented 2 years ago

Great!

You're welcome :)