1

I implemented a custom auth backend as advised by django doc I have two methods - authenticate and get_user.

I confirmed that my custom 'authenticate' method is called and returns a proper user but in request.user I'm always getting AnonymousUser and my "get_user" method is never get called.

It could be something with sessions, because when I decode my session the only thing I see there is "{u'django_language': u'en'}"

What am I missing?

Here is my custom SSOBackend

class SSOBackend(object):
    """
    My authentication backend
    """

    def authenticate(self, *args, **kwargs):
        """
        Authenticate user using access_token and refresh_token
        """

        access_token = kwargs.get('access_token')
        refresh_token = kwargs.get('refresh_token')
        user_info = _get_user_info(access_token, refresh_token)
        try:
            user = User.objects.get(username=user_info['user_id'])
        except User.DoesNotExist:
            import uuid
            random_password = uuid.uuid4()
            user = User(username=user_info['user_id'], password=random_password)
            user.save()

        return user


    # Required for your backend to work properly - unchanged in most scenarios
    def get_user(self, user_id):
        try:
            logger.info("SSOBackend.get_user:  User_id = %s" %user_id)
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

I'm logging user in using my custom Middleware:

class SSOMiddleware(object):

    def process_view(self, request, view_func, view_args, view_kwargs):

        if 'state' in request.GET and 'code' in request.GET and '/auth-callback/' in request.get_full_path():

            redirect_uri = "http://{domain}/sso/auth-callback/".format(domain=request.get_host())
            next_page = "/"

            
            code = request.GET['code']

            # where to redirect after successful authentication
            next_page = request.GET['state']

            config = SSOConfig()
            token_url = config.token_url
            client_id = config.client_id
            client_secret = config.client_secret

            # retrieve access token using code
            headers = {"content-type": "application/x-www-form-urlencoded", "host": "www.myproject.com"}
            payload = ("grant_type=authorization_code&code={code}&client_id={client_id}&"
                        "client_secret={client_secret}&redirect_uri={redirect_uri}").format(**locals())

            response = requests.post(token_url, data=payload, headers=headers)

            if response.status_code != 200:
                return HttpResponseBadRequest(_("Bad Request"))

            authorization_info = response.json()

            access_token = authorization_info["access_token"]
            refresh_token = authorization_info["refresh_token"]
            authenticate(access_token=access_token, refresh_token=refresh_token)

            return HttpResponseRedirect(next_page)
 
        return None

Here is what I have in my settings.py:

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'myproject.sso.middleware.SSOMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.locale.LocaleMiddleware',
)

AUTHENTICATION_BACKENDS = (
    'myproject.sso.backends.SSOBackend',
    'django.contrib.auth.backends.ModelBackend',
)
  • I'm running into the same thing. We have ratelimiting keys based on a user property, and since the real User object isn't getting called, it's impossible to use the right ratelimiting. – rschwieb Nov 13 '15 at 20:09
  • Note here is that your `get_user` method defined on your auth-backend class takes the User models primary-key to resolve the user. – holmberd Aug 02 '18 at 17:22

1 Answers1

0

Answer on the behalf of the author of the question:

I figured that out. I'm missing these lines after authenticating the user:

from django.contrib.auth import authenticate, login

....

user = authenticate(access_token=access_token, refresh_token=refresh_token)

if user is not None:
    login(request, user)