5

I'm using Django 1.8.4 on Python 3, and attempting to create an auth backend which validates a cookie from a legacy ColdFusion web site and create / log the Django user in after checking the value in a database. In settings, I am including the backend:

AUTHENTICATION_BACKENDS = (
    'site_classroom.cf_auth_backend.ColdFusionBackend',
)

And the code for the backend itself; SiteCFUser is a model against the SQL Server database user model which contains the active cookie token value:

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from users.models import SiteCFUser


class ColdFusionBackend(ModelBackend):
    """
    Authenticates and logs in a Django user if they have a valid ColdFusion created cookie.

    ColdFusion sets a cookie called "site_web_auth"
    Example cookie: authenticated@site+username+domain+8E375588B1AAA9A13BE03E401A02BC46
    We verify this cookie in the MS SQL database 'site', table site_users, column user_last_cookie_token
    """

    def authenticate(self, request):
        User = get_user_model()

        print('Hello!')
        token=request.COOKIES.get('site_web_auth', None)
        print('Token: ' + token)
        cookie_bites = token.split('+')

        if cookie_bites[0] != "authenticated@site":
            # Reality check: not a valid site auth cookie
            return None

        username = cookie_bites[1]
        cf_token = cookie_bites[3]

        try:
            site_user = SiteCFUser.objects.using('mssqlsite').filter(cf_username=username)
        except:
            # No user found; redirect to login page
            return None

        if site_user[0].cftoken == cf_token:
            try:
                # Does the user exist in Django?
                user = User.objects.get(username=username)
            except:
                # User does not exist, has a valid cookie, create the User.
                user = User(username=username)
                user.first_name = site_user[0].cf_first_name
                user.last_name = site_user[0].cf_last_name
                user.email = site_user[0].cf_email
                user.save()
        else:
            return None

    def get_user(self, user_id):
        User = get_user_model()

        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

The problem is, the backend doesn't seem to be called when hitting a URL with a view with @login_required, or even trying to log in through a form with username and password. If I force an error by changing the name of the class in settings, or change the name of the class in cf_auth_backend.py, I do get an error. However, none of the print statements show up in the console. I'm clearly missing something here: any idea what I'm not doing right?

1
  • All @login_required does is redirect to the login page if the user is not already authenticated. You'll need to show the code for that view. Commented Oct 4, 2015 at 13:39

2 Answers 2

4

While the accepted answer might have helped the OP, it's not a general answer to the question's title.

Authentication back ends do work simply by listing them in AUTHENTICATION_BACKENDS. But they may appear to be ignored for various reasons, e.g.:

  • urls.py needs to point to something like django.contrib.auth.views.login

    url(r'^accounts/login/$', django.contrib.auth.views.login)
    

    if it's pointing to some other authentication app. AUTHENTICATION_BACKENDS may not work.

  • the authenticate() method must accept a password keyword, either through password=None or **kwargs. Probably true for username too. It won't be called if it doesn't accept that keyword argument.
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for that second tip! I had started from an old example backend and it didn't have the updated function signature for authenticate.
Just stumbled accross this problem two years later... It seems that the method signature of authenticate has changed again, it now seems to require a request parameter.
3

Authentication backends doesn't work that way. They won't be called on each request or on requests where authentication is required.

If you want to log in user based on some cookie, you should call authentication in middleware.

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.