Search code examples
djangooauthwagtaildjango-authentication

Wagtail manually login user


I have a wagtail application that needs to login and authenticate users for the /admin section using OAuth. The interaction with the OAuth provider works fine is just at the end of the authorize view I am getting a Too many redirects error. Here is my gist:

SESSION_KEY = 'access_token'

oauth = OAuth()
oauth_client = oauth.remote_app(#oauth client setup here)

Views

def login(request):
    """
    This view is redirecting to my oauth provider, log the user
    and redirect back to /authorize with the data in the request.
    """
    return HttpResponseRedirect(oauth_client.authorize(
        callback='http://localhost/admin/authorize'))


def authorize(request):    
    resp = oauth_client.authorized_response(request.GET)    
    request.session[SESSION_KEY] = (resp['access_token'], '')
    data = baton.get('/oauth/me')
    username = json.loads(data.data).get('username')

    user, _ = User.objects.get_or_create(
        username=username,
        defaults={'password': username, 'is_superuser': True}
    )
    auth_user = authenticate(username=username, password=username)
    login(auth_user)

    return HttpResponseRedirect('/admin')

Urls

urlpatterns = [
    url(r'^admin/login', login, name='login'),
    url(r'^admin/authorize', authorize, name='authorize'),

    url(r'^admin/', include(wagtailadmin_urls)),
]

The Too many redirects I see in the browsers happens when the authorize view validates all the logic and tries to redirect to /admin but I think what is happening is that Wagtail then is redirecting again to /login but I though authenticating and login a user should be enough for Wagtail, apparently not.

Any ideas how to overcome this issue, or programmatically login a user to the Wagtail admin.


Solution

  • The line login(auth_user) is calling the login view you defined above, but you're passing a user object instead of a request. Was this supposed to be calling the login function from django.contrib.auth? If so, you'll need to give it a distinct name that doesn't clash with the view, perhaps with:

    from django.contrib.auth import login as auth_login
    

    (In this case, you'll still need to fix the parameters of your login / auth_login call, as it takes both a request and a user - see the docs at https://docs.djangoproject.com/en/3.0/topics/auth/default/#django.contrib.auth.login)