Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discussion: what is the benefit of going through the authentication backend system? #107

Open
silviogutierrez opened this issue Jan 11, 2024 · 5 comments

Comments

@silviogutierrez
Copy link

I was surprised when setting up this library that you needed an additional auth backend.

I've hacked together versions of this before (far less sophisticated) and ultimately just parse the token and call django.contrib.auth.login directly on the user if the token is valid.

I'd say it's not a big deal, but noticed now I have to pass a backend to login every time I do it for other purposes. Say, after registering or in my login-as-other-user tools. Things outside sesame.

Couldn't this library just parse the token as it currently does then directly call login without going through the backend chain?

Eases the setups — only decorators required — and allows login to keep working for other purposes.

For reference,

from django.contrib.auth import login

def user_sign_up():
    # Form processing logic that gives us a a user.
    # But no password, we have users set up passwords after.
    user = form.save()
    login(request, user)

After configuring django-sesame:

from django.contrib.auth import login

def user_sign_up():
    # Form processing logic that gives us a a user.
    # But no password, we have users set up passwords after.
    user = form.save()
    login(request, user, "django.contrib.auth.backends.ModelBackend")
@aaugustin
Copy link
Owner

The pattern you are showing (user = form.save()) logs a user in while bypassing all security features of Django. If you authenticated the user with authenticate(), the user would have a user.backend attribute and you wouldn't need to specify the authentication backend explicitly. That contributes to the issue here.


Providing a custom authentication backend is the recommended way to authenticate against another source in Django: https://docs.djangoproject.com/en/stable/topics/auth/customizing/

It is also necessary for authenticate() to work as documented.

That being said, some use cases can work without the authentication backend. You can remove it from your configuration. If all API you need still work, I think you're good to go.


I'm going to take a deeper look at this. I'm keeping it open as a documentation issue.

@aaugustin
Copy link
Owner

aaugustin commented Jan 12, 2024

Wait - get_user() calls authenticate() so nothing will work without the authentication backend.

@silviogutierrez
Copy link
Author

Right, it's currently needed as is.

But really, the meat of the library is in parse_token.

So just doing parse_token() + login() in get_user would work. No need to go through the backend system.

I guess I see custom backends as "authenticating against another source" where source is "active directory" or "SSO" or "something other than a local DB table".

Here's simplified pseudo code for get_user:

from django.contrib.auth import login

def get_user(request_or_sesame, scope="", max_age=None, *, update_last_login=None):
    # ... setup logic

    if user := parse_token(...args):
        login(
            request,
            user,
        )

    if update_last_login is None:
        update_last_login = settings.ONE_TIME
    if update_last_login:
        user.last_login = timezone.now()
        user.save(update_fields=["last_login"])

    return user

Either way, library works great as is. Just looking to simplify the setup (since AUTHENTICATION_BACKENDS isn't in the default settings file generated by startproject). I'll close this.

@aaugustin
Copy link
Owner

I'm not sure I will do something but I'd like to think a bit more about it :-) I'm keeping it open for myself. Thanks for sharing that feedback!

@alfonsrv
Copy link

alfonsrv commented Aug 27, 2024

Another thing to consider might be that by simply calling authenticate with the sesame token leads to signal user_login_failed to just get the sesame token in credentials without any further context on the user or why the login failed (e.g. token expired)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants