Skip to content

fix(passkeys): get actual identifier field (e.g. email) instead of username, to allow for custom user models - #78

Closed
ganiyevuz wants to merge 2 commits into
mkalioby:v2.1from
ganiyevuz:v2.1
Closed

fix(passkeys): get actual identifier field (e.g. email) instead of username, to allow for custom user models#78
ganiyevuz wants to merge 2 commits into
mkalioby:v2.1from
ganiyevuz:v2.1

Conversation

@ganiyevuz

@ganiyevuz ganiyevuz commented May 4, 2026

Copy link
Copy Markdown
Contributor

Fixed authentication backend crash when using custom username fields (e.g. email or phone). The backend now safely handles requests without the passkeys field and works correctly with any configured USERNAME_FIELD, avoiding exceptions during standard login flows. Additionally, username is passed as None when not provided to prevent unintended behavior in ModelBackend.authenticate.

https://github.com/django/django/blob/50bbf71bbd51616e2ce48785336ca3746fbe5f24/django/contrib/auth/backends.py#L66

ganiyevuz added 2 commits May 4, 2026 14:49
…ername, to allow for custom user models

Exception: Can't find 'passkeys' key in request.POST, did you add the hidden input?
@mkalioby

mkalioby commented May 4, 2026

Copy link
Copy Markdown
Owner

@ganiyevuz , can you please provide an example User Model and usage to understand how this shall work.

@ganiyevuz

Copy link
Copy Markdown
Contributor Author
class User(AbstractBaseUser, PermissionsMixin):

    class UserType(TextChoices):
        SUPERADMIN = "super", _("Super Admin")
        ADMIN = "admin", _("Admin")
        SUPPORT = "support", _("Support")

    first_name = CharField(_("first name"), max_length=150, blank=True)
    avatar = ImageField(
        validators=[
            FileExtensionValidator(allowed_extensions=["jpg", "jpeg", "png", "webp"]),
            validate_file_size,
        ],
        upload_to="avatars/", null=True, blank=True, verbose_name=_("avatar")
    )
    email = EmailField(
        _("email address"),
        unique=True,
        blank=False,
        error_messages={
            "unique": _("A user with that email already exists."),
        },
    )
    role = CharField(
        _("role"),
        max_length=20,
        choices=UserType.choices,
        default=UserType.SUPPORT,
        help_text=_("Role of the user in the system."),
    )
    is_staff = BooleanField(
        _("staff status"),
        default=False,
        help_text=_("Designates whether the user can log into this admin site."),
    )
    is_active = BooleanField(
        _("active"),
        default=True,
        help_text=_(
            "Designates whether this user should be treated as active. "
            "Unselect this instead of deleting accounts."
        ),
    )
    company = ForeignKey('companies.Company', on_delete=CASCADE, null=True, blank=True,
                         verbose_name=_("company"))
    notification_enabled = BooleanField(default=True)
    notification_sound_enabled = BooleanField(default=True)
    date_joined = DateTimeField(_("date joined"), auto_now_add=True)

    objects = UserManager()

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = []

    class Meta:
        verbose_name = _("user")
        verbose_name_plural = _("users")

as you can see there is no email field in my User model and instead i am using email so when i try to use im getting username as none because of actual identifier is in different field.

@mkalioby

Copy link
Copy Markdown
Owner

Done as published as v2.2b1.

pip install django-passkeys==2.2b1

@mkalioby mkalioby closed this May 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants