0

I'm having trouble using basic auth with django, here's my config:

MIDDLEWARE_CLASSES = [
    'request_id.middleware.RequestIdMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.RemoteUserMiddleware', # <<<<<===
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

AUTHENTICATION_BACKENDS  = [
    'django.contrib.auth.backends.RemoteUserBackend',
    'django.contrib.auth.backends.ModelBackend',
]

and my view:

def api_list_things(request, intake_id=None):
    if not request.user.is_authenticated():
        return JsonResponse({'message': 'Not authenticated'}, status=403)
    return JsonResponse({'message': 'ok'})

But when I do curl -v http://user:pass@localhost:8000/api/list_things/ I get the unauthenticated error:

* Hostname was NOT found in DNS cache                    
*   Trying ::1...                                        
* connect to ::1 port 8000 failed: Connection refused    
*   Trying 127.0.0.1...                                  
* Connected to localhost (127.0.0.1) port 8000 (#0)      
* Server auth using Basic with user 'd'                  
> GET /trs/api/intakes/ HTTP/1.1                         
> Authorization: Basic dXNlcjpwYXNz                              
> User-Agent: curl/7.38.0                                
> Host: localhost:8000                                   
> Accept: */*                                            
>                                                        
* HTTP 1.0, assume close after body                      
< HTTP/1.0 403 Forbidden                                 
< Vary: Cookie                                           
< X-Frame-Options: SAMEORIGIN                            
< Content-Type: application/json                         
< Connection: close                                      
< Server: Werkzeug/0.11.10 Python/3.4.2                  
< Date: Wed, 20 Jul 2016 14:16:32 GMT                    
<                                                        
* Closing connection 0                                   
{"message": "Not authenticated"}%                        

I don't see where I'm wrong, maybe somebody can help me ?

damio
  • 6,041
  • 3
  • 39
  • 58

2 Answers2

2

Django does not support Basic HTTP auth by itself, what django.contrib.auth.backends.RemoteUserBackend actually does is described in the docs.

With this setup, RemoteUserMiddleware will detect the username in request.META['REMOTE_USER'] and will authenticate and auto-login that user using the RemoteUserBackend.

The REMOTE_USER env variable should be set by a web server sitting in front of Django (for eg. apache).

If you just want to support the Authorization header, this custom authentication backend might help: https://www.djangosnippets.org/snippets/243/ (from here)

Community
  • 1
  • 1
Kedar
  • 1,648
  • 10
  • 20
  • Thanks, just so you know the snippet doesn't work with python 3, here's a version with all the fixes included: https://github.com/m7v8/django-basic-authentication-decorator/blob/master/django_basic_auth.py – damio Jul 21 '16 at 09:30
1
import basicauth
from django.contrib.auth import authenticate

def api_list_things(request, intake_id=None):
    user_pass = basicauth.decode(request.META['HTTP_AUTHORIZATION'])
    if authenticate(username=user_pass[0], password=user_pass[1]):
        return JsonResponse({'message': 'Authenticated'}, status=200)
    return JsonResponse({'message': 'Not Authenticated'})
  • 1
    The community encourages adding explanations alongisde code, rather than purely code-based answers (see [here](https://meta.stackoverflow.com/questions/300837/what-comment-should-i-add-to-code-only-answers)) – Ahmet Feb 11 '21 at 19:45