title: Custom django authentication backend doesn't log user in first time, but works second time
body: <p>So I'm using Rdio to login and create users, and wrote a backend to handle its oauth. The first time you try to sign in using Rdio, it creates a user and an attached Rdio user, but it doesn't create a session and return the session cookie.</p>
  
  <p>The flow is like any oauth2 flow: you press a button on my app, it redirects w/ get params to Rdio, and Rdio calls a callback view on my app (along with a code in the GET params). In that callback view, I call authenticate:</p>
  
  <pre><code>class RdioCallbackView(View):
  def get(self, request):
      """ here, you need to create and auth a django user and create and tie the rdio user's stuff to it """
      if request.user.is_authenticated() == False:
          try:
              rdio_code = request.GET['code']
          except KeyError:
              return redirect(reverse('login'))
          # authenticate
          user = auth.authenticate(rdio_code=rdio_code)
          if user is not None and user.is_active:
              auth.login(request, user)
          else:
              return render(request, 'home/login.html', {'rdio_url': create_rdio_auth_url(), 'message': "That code didn't seem to work"})
      else:
          # user exists!
          user = request.user
      return HttpResponseRedirect(reverse('the-next-view'))
  </code></pre>
  
  <p>The custom auth backend looks like this:</p>
  
  <pre><code>class RdioBackend(object):
  def authenticate(self, rdio_code=None):
      token_info = exchange_rdio_code(rdio_code)
      try:
          access_token = token_info['access_token']
          refresh_token = token_info['refresh_token']
      except KeyError:
          return None
      except TypeError:
          # the code was probably already used.
          return None
  
      rdio_user_dict = get_rdio_user_for_access_token(access_token)
      rdio_key = rdio_user_dict['key']
  
      try:
          rdio_user = RdioUser.objects.get(rdio_id=rdio_key)
          rdio_user.access_token = access_token
          rdio_user.refresh_token = refresh_token
          rdio_user.save()
          user = rdio_user.user
      except RdioUser.DoesNotExist:
          user = User.objects.create(username=rdio_key)
          user.set_unusable_password()
          rdio_user = RdioUser.objects.create(
              rdio_id = rdio_key,
              access_token = access_token,
              refresh_token = token_info['refresh_token'],
              user = user,
              )
      return user
  
  def get_user(self, user_id):
      try:
          return User.objects.get(pk=user_id)
      except User.DoesNotExist:
          return None
  </code></pre>
  
  <p>And that's where things get weird. It doesn't seem to make a new Session object, and definitely doesn't return a session cookie. However, when I go back and do the Rdio login again for a second time, it returns a session cookie, makes the session on the backend, and login and auth work perfectly.</p>
  
  <p>And I think my AUTHENTICATION_BACKENDS settings is right:</p>
  
  <pre><code>AUTHENTICATION_BACKENDS = (
  'appname.backend.RdioBackend',
  'django.contrib.auth.backends.ModelBackend',
  )
  </code></pre>
  
  <p>Edit: More possibly relevant info:
  The views that it's redirecting to have a LoginRequiredMixin:</p>
  
  <pre><code>class LoginRequiredMixin(object):
  @classmethod
  def as_view(cls, **initkwargs):
      view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
      return login_required(view)
  </code></pre>
  
  <p>And in RdioCallbackView, when I change the final line from <code>return HttpResponseRedirect(reverse('the-next-view'))</code> to instead just serve the template directly with <code>return render(request, 'path/to.html', param_dict)</code>, it does serve the cookie and make a sessionid, but then it deletes it from the DB and from the browser the moment I navigate away from that screen.</p>